题目: https://codeforces.com/contest/776/problem/D
题意: 有n个房间,由m个开关控制。每个房间一定是由两个开关控制。每个房间有一个初始的是否解锁的状态。问你能否让所有房间都解锁。
题解: 若控制一个房间的开关为a,b。一个开关若开为a,不开为a+m。则若房间原来开着,就为(a,b)或(a+m,b+m)。原来没开就为(a,b+m)或(a+m,b)。用并查集并起来,最后如果有a和a+m在同一个集合就为NO。
可是就是想不到啊,qaq怎么这么菜啊
还可以用2-sat做,到时候复习完2-sat再写一遍吧
#include<bits/stdc++.h>
using namespace std;
int r[100010],y[100010][3],ly[100010],father[200110];
int findfather(int k){if(father[k]==k)return father[k];else return father[k]=findfather(father[k]);}
void ak(int aa,int bb)
{
int a1=findfather(aa);
int b1=findfather(bb);
if(a1!=b1)father[a1]=b1;
}
int main()
{
int n,m,i,j,lx,x,k1,k2;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",&r[i]);
for(i=1;i<=m;i++)
{
scanf("%d",&lx);
for(j=1;j<=lx;j++)
{
scanf("%d",&x);
y[x][++ly[x]]=i;
}
}
for(j=1;j<=2*m;j++)father[j]=j;
for(i=1;i<=n;i++)
{
k1=y[i][1];k2=y[i][2];
if(r[i]==0)
{
ak(k1,k2+m);
ak(k1+m,k2);
}
else
{
ak(k1,k2);
ak(k1+m,k2+m);
}
}
for(i=1;i<=m;i++)if(findfather(i)==findfather(i+m)){printf("NO");return 0;}
printf("YES");
return 0;
}