题意:给你n个门的状态1表示开,每个门被两个开关控制然后给你每个开关控制哪些门的信息,问你能不能将这些门全部打开
题解:2-sat。对于已经开了的门,要么控制它的两个开关都开,要么都关,对于没有开的门只能一个开关开,一个关。
开和关是两种状态,我们将属于同一种状态的开关并查集合到一起,然后check一下是否满足我们的结论,如果满足则一定可以把门打开。
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <queue> #include <vector> #include <cstring> #include <iomanip> #include <set> #include<ctime> #include<unordered_map> //CLOCKS_PER_SEC #define se second #define fi first #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define Pli pair<ll,int> #define ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const int N=3e5+10; const ull base=163; const int INF=0x3f3f3f3f; using namespace std; int fa[N]; int last[N]; bool door[N]; int f(int x){ return fa[x]==x?x:fa[x]=f(fa[x]); } int main(){ fio; int n,m; cin>>n>>m; for(int i=1;i<=2*m;i++)fa[i]=i; for(int i=1;i<=n;i++){ cin>>door[i]; } for(int i=1;i<=m;i++){ int t;cin>>t; for(int j=1;j<=t;j++){ int x; cin>>x; if(last[x]){ if(door[x]){ int l=f(last[x]),r=f(i); if(l!=r){ fa[l]=r; } l=f(last[x]+m),r=f(i+m); if(l!=r)fa[l]=r; } else{ int l=f(last[x]+m),r=f(i); if(l!=r){ fa[l]=r; } l=f(last[x]),r=f(i+m); if(l!=r)fa[l]=r; } } else{ last[x]=i; } } } int flag=0; for(int i=1;i<=m;i++){ if(f(i)==f(i+m))flag=1; } if(flag)cout<<"NO"; else cout<<"YES "; return 0; }