Codeforces - The Door Problem

题目链接:Codeforces - The Door Problem


如果从灯泡的角度思考,比较麻烦。我们直接想开关,每个开关只有两种选择。

然后对于每个灯泡可以确定开关的选择,最后2-SAT即可。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10;
int n,m,a[N];
int low[N],dfn[N],scc[N],vis[N],co,cnt;	stack<int> s;
vector<int> g[N],v[N];
char *fs,*ft,buf[1<<15];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
inline int read(){
    int x=0,f=1; char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
inline void add(int a,int b){g[a].push_back(b);}
void Tarjan(int x){
	low[x]=dfn[x]=++cnt; s.push(x),vis[x]=1;
	for(auto to:g[x]){
		if(!dfn[to]) Tarjan(to),low[x]=min(low[x],low[to]);
		else if(vis[to])	low[x]=min(low[x],dfn[to]);
	}
	if(low[x]==dfn[x]){
		co++;	int u;
		do{
			u=s.top(); s.pop(); vis[u]=0; scc[u]=co;
		}while(u!=x);
	}
}
signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)	a[i]=read();
	for(int i=1,k,x;i<=m;i++){
		k=read();	while(k--)	x=read(),v[x].push_back(i);	
	}
	for(int i=1,x,y;i<=n;i++){
		x=v[i][0],y=v[i][1];
		if(a[i])	add(x,y),add(y,x),add(x+m,y+m),add(y+m,x+m);
		else	add(x,y+m),add(y,x+m),add(x+m,y),add(y+m,x);
	}
	for(int i=1;i<=m*2;i++)	if(!dfn[i])	Tarjan(i);
	for(int i=1;i<=m;i++)	if(scc[i]==scc[i+m])	return puts("NO");
	puts("YES");
	return 0;
}
发布了604 篇原创文章 · 获赞 242 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104362296
今日推荐