CodeForces 776D The Door Problem【并查集】

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 }
时间: 2024-11-03 21:25:50

CodeForces 776D The Door Problem【并查集】的相关文章

Codeforces 445B DZY Loves Chemistry(并查集)

题目链接:Codeforces 445B DZY Loves Chemistry 题目大意:有若干种化学药品,给出两两会反应的关系,现在要将药物依次放入一个容器中,容器中的化学药品可以互相反应,如果当前放入的药品能与已经在容器中的某一药品反应,那么危险值翻倍,即*2,初始值为1,求一顺序,使得为危险值最大. 解题思路:并查集求最小联通分量s,2n?s即为答案. #include <cstdio> #include <cstring> #include <iostream>

Codeforces 776D.The Door Problem (dfs二分图判定 / 并查集)

题目链接: http://codeforces.com/problemset/problem/776/D 题意: n扇门,m个开关(n,m<=1e5),每个开关控制若干个门,反转开关门状态变化,每个门正好被两个开关控制,问是否有可能把所有门的状态置为1? 思路: from: http://blog.csdn.net/jeremy1149/article/details/56839453 方法一:二分图染色 注意到一个门只被两个开关控制 若门初始为0 则控制它的两个开关状态相反,门初始为1则 要求

Codeforces 731C:Socks(并查集)

http://codeforces.com/problemset/problem/731/C 题意:有n只袜子,m天,k个颜色,每个袜子有一个颜色,再给出m天,每天有两只袜子,每只袜子可能不同颜色,问要让每天的袜子是相同颜色的,要重新染色的袜子数最少是多少. 思路:并查集合并,将同一天的袜子合并起来,然后就形成了cnt个集合,每个集合都是独立的,因此排序,找出每个集合里面袜子颜色相同的最多的是哪个颜色,然后把其他不属于这个颜色的都染成这个颜色,那么这样重新染色的袜子数是最少的.然后每个集合的答案

loj6157 A^B Problem (并查集)

题目: https://loj.ac/problem/6157 分析: 这种树上异或,一般是采用分位考虑,但是这题即使分位,也会发现非常不好处理 这里考虑维护一个点到其根的路径的异或值 用并查集去检测m个测试 若s和t不在一个并查集内: 挑出s的根f1,t的根f2,father[f1]=f2,并且发现w[f1]=c^w[s]^w[t] 若s和t在一个并查集内: 那么首先这个并查集内的所有点的w值都已经求过了,那么只要check一下c是否等于w[s]^w[t]即可 如果最后并查集数量多于一个,那么

CodeForces 731C Socks (DFS或并查集)

题意:有n只袜子,k种颜色,在m天中,问最少修改几只袜子的颜色,可以使每天穿的袜子左右两只都同颜色. 析:很明显,每个连通块都必须是同一种颜色,然后再统计最多颜色的就好了,即可以用并查集也可以用DFS. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include

CodeForces 400D (最短路+并查集) Dima and Bacteria

 Description Dima took up the biology of bacteria, as a result of his experiments, he invented k types of bacteria. Overall, there are n bacteria at his laboratory right now, and the number of bacteria of type i equals ci. For convenience, we will

Codeforces 469 D. Two Sets (并查集)

题目链接:Two Sets 题意: 有n个数,要分成A.B两组,要求如果x∈A则a-x∈A,如果x∈B则b-x∈B,问是否存在一种符合要求的分法. 题解: 并查集,先增加两个点表示A和B集合的根,对于一个数x,如果a-x存在就把x和a-x放一起,否则就将x和B的根相连,如果b-x存在就把x和b-x放一起,否则就将x和A的根相连,最后看一下A和B集合的根是否相连就可以判断出有没有解了,至于分法就看这个数是和A的根相连还是B的根相连了. 1 #include<bits/stdc++.h> 2 us

CodeForces 828C String Reconstruction(并查集思想)

题意:给你n个串,给你每个串在总串中开始的每个位置,问你最小字典序总串. 思路:显然这道题有很多重复填涂的地方,那么这里的时间花费就会特别高. 我们维护一个并查集fa,用fa[i]记录从第i位置开始第一个没填涂的位置,那每次都能跳过涂过的地方.每次填完当前格就去填find(fa[i + 1]). ps:一定要合并,不然超时. 代码: #include<stack> #include<vector> #include<queue> #include<set>

Codeforces 828C String Reconstruction【并查集巧妙运用】

LINK 题目大意 给你n个串和在原串中的出现位置,问原串 思路 直接跑肯定是GG 考虑怎么优化 因为保证有解,所以考虑过的点我们就不再考虑 用并查集维护当前每个点之后最早的没有被更新过的点 然后就做完了,很巧妙对吧 c++//Author: dream_maker #include<bits/stdc++.h> using namespace std; //---------------------------------------------- //typename typedef lo