1. 程式人生 > >CodeForces 776D The Door Problem【並查集】

CodeForces 776D The Door Problem【並查集】

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(int
x,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【並查集】