Codeforces - Two Sets

题目链接:Codeforces - Two Sets


要么属于集合A,要么属于集合B。

显然的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,a,b,x[N];
int low[N],dfn[N],scc[N],idx,vis[N],cnt,co;	stack<int> st;
map<int,int> mp;	vector<int> g[N];
inline void add(int a,int b){g[a].push_back(b);}
void Tarjan(int x){
	dfn[x]=low[x]=++cnt;	vis[x]=1;	st.push(x);
	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(dfn[x]==low[x]){
		co++;	int u;
		do{
			u=st.top();	st.pop(); vis[u]=0; scc[u]=co;
		}while(u!=x);
	}
}
signed main(){
	ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
	cin>>n>>a>>b;
	for(int i=1;i<=n;i++)	cin>>x[i],mp[x[i]]=i;
	for(int i=1;i<=n;i++){
		int pos1=mp[a-x[i]],pos2=mp[b-x[i]];
		if(!pos1&&!pos2)	return cout<<"NO",0;
		if(pos1&&!pos2)	add(i+n,i),add(pos1+n,pos1);
		if(!pos1&&pos2)	add(i,i+n),add(pos2,pos2+n);
		if(pos1&&pos2)	add(i,pos1),add(i,pos2),add(i+n,pos1+n),add(i+n,pos2+n);
	}
	for(int i=1;i<=n*2;i++)	if(!dfn[i])	Tarjan(i);
	for(int i=1;i<=n;i++)	if(scc[i]==scc[i+n])	return cout<<"NO",0;
	cout<<"YES"<<'\n';
	for(int i=1;i<=n;i++)	cout<<(scc[i]>scc[i+n])<<' ';
	return 0;
}
发布了553 篇原创文章 · 获赞 242 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104225493