CodeForces 776D The Door Problem【並查集】
阿新 • • 發佈:2017-07-03
merge cnblogs 表示 turn pro name 所有 force mes
CodeForces 776D The Door Problem【並查集】
並查集
設 f 1--m 表示 開的情況 m+1--2*m 表示關的情況
對於每盞燈
如果他 是關的 則 x--y x+m--y+m 表示要同關 或者同開
如果他 是開的 則 x+m--y x--y+m 表示一個關 一個開
如果一盞燈 的 x 連向 了 x+m 則表示是矛盾了 那麽久是錯誤的
題意:給你n個門,和m組開關,每扇門都有兩個開關控制,每個開關控制x扇門,
如果選擇了某組開關,則使這組開關裏的每個開關控制的所有的門按狀態取反,
問你是否能使得所有的門狀態為1
解析:將每個開關拆分成兩個點,選這個開關和不選這個開關(x,x+m),根據每扇門的狀態來,
如果狀態為1,則需要同時選擇這兩個開關或者不選,如果狀態為零,那麽只能選擇一個開關。
根據上面的情況做並查集,然後判斷第i(選)組開關和i+m(選)是否聯通,有則無解
1 #include <cstdio> 2 using namespace std ; 3 4 const int maxn = 100011 ; 5 int n,m,k ; 6 int light[ maxn ],g[maxn][3],f[maxn*2] ; 7 8 inline int getfather(int x) 9 { 10 if(x==f[x]) return x ; 11 f[x] = getfather(f[x]) ; 12 return f[x] ; 13 } 14 15 inline void merge(intx,int y) 16 { 17 int xx,yy ; 18 xx = getfather(x) ; yy = getfather(y) ; 19 if(xx!=yy) f[xx] = yy ; 20 } 21 22 int main() 23 { 24 scanf("%d%d",&n,&m) ; 25 for(int i=1;i<=n;i++) 26 scanf("%d",&light[ i ]) ; 27 int x,y ; 28 for(int i=1;i<=m;i++)29 { 30 scanf("%d",&k) ; 31 for(int j=1;j<=k;j++) 32 scanf("%d",&x) , g[x][++g[x][0]] = i ; 33 } 34 35 for(int i=1;i<=2*m;i++) f[ i ] = i ; 36 for(int i=1;i<=n;i++) 37 { 38 x = g[i][1] ; 39 y = g[i][2] ; 40 if(light[ i ]) 41 { 42 merge(x,y) ; 43 merge(x+m,y+m) ; 44 } 45 else 46 { 47 merge(x,y+m) ; 48 merge(y,x+m) ; 49 } 50 } 51 52 bool flag = 0 ; 53 int xx,yy ; 54 for(int i=1;i<=m;i++) 55 { 56 xx = getfather( i ) ; 57 yy = getfather( i+m ) ; 58 if(xx==yy) flag = 1 ; 59 } 60 if(flag) 61 printf("NO\n") ; 62 else 63 printf("YES\n") ; 64 return 0 ; 65 }
CodeForces 776D The Door Problem【並查集】