【题解】CF776D
一:【题意】
现在给出一些门的状态(开或者关),你还有一些遥控器,每个可以使得一个集合的门的开关状态翻转,每个门只被最多两个遥控器控制,问是否能让所有门打开
\(n,m<=10^5\)
二:【解法】
对于每个遥控器,1表示按,0表示不按
门初始为关:则两个遥控器仅有一个为1
门初始为开:则两个遥控器同0或同1
可以转化为2-SAT求解
三:【代码】
#include<bits/stdc++.h>
#define inf 2e9
#define Pair pair<int,int>
#define l first
#define r second
using namespace std;
const int N=1e5+10;int n,m;
int a[N];
Pair bl[N];
vector<int> mp[N*2];
int low[N*2],dfn[N*2],cnt;
int scc[N*2],idx;
vector<int> st;
void Tarjan(int u,int pa){
low[u]=dfn[u]=++cnt;
st.push_back(u);
for(auto v:mp[u]){
if(v==pa) continue;
if(!dfn[v]){
Tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else if(!scc[v]) low[u]=min(low[u],dfn[v]);
}
//cout<<"==>"<<low[u]<<" "<<dfn[u]<<"\n";
if(low[u]==dfn[u]){
idx++;
while(1){
int x=st.back();st.pop_back();
scc[x]=idx;
if(x==u) break;
}
}
}
void SCC(){
for(int i=1;i<=2*m;i++){
if(!dfn[i]) Tarjan(i,0);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++){
int x;cin>>x;
while(x--){
int k;cin>>k;
if(bl[k].l) bl[k].r=i;
else bl[k].l=i;
}
}
for(int i=1;i<=n;i++){
int l=bl[i].l,r=bl[i].r;
//cout<<"-->"<<l<<" "<<r<<"\n";
if(a[i]==0){
mp[l].push_back(r+m);
mp[l+m].push_back(r);
mp[r].push_back(l+m);
mp[r+m].push_back(l);
}
else{
mp[l].push_back(r);
mp[l+m].push_back(r+m);
mp[r].push_back(l);
mp[r+m].push_back(l+m);
}
}
SCC();
//for(int i=1;i<=n;i++) cout<<scc[i]<<" "<<scc[i+n]<<"\n";
for(int i=1;i<=m;i++){
if(scc[i]==scc[i+m]){
cout<<"NO\n";
return 0;
}
}
cout<<"YES\n";
return 0;
}

浙公网安备 33010602011771号