题目链接: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;
}