【模板】2—SAT問題
阿新 • • 發佈:2018-11-10
參考題目:洛谷P4782
解析:
聯賽完後統一更模板題題解。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c= gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int N=2000006;
vector<int> edge[N];
int dfn[N],low[N],dfs_clock;
int scc[N],scc_clock;
int sta[N],top;
bool insta[N];
inline void tarjan(int u){
dfn[u]=low[u]=++dfs_clock;
sta[++top]=u;
insta[u]=true;
for(int re e=0;e<edge[u] .size();++e){
int re v=edge[u][e];
if(dfn[v]){
if(insta[v])low[u]=min(low[u],dfn[v]);
}
else tarjan(v),low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u]){
++scc_clock;
do{
scc[u]=scc_clock;
u=sta[top--];
insta[u]=false;
}while(low[u]!=dfn[u]);
}
}
int n, m;
inline bool _2_SAT(){
for(int re i=1;i<=n*2;++i){
if(!dfn[i])tarjan(i);
}
for(int re i=1;i<=n;++i)if(scc[i]==scc[i+n])return false;
return true;
}
signed main(){
n=getint();
m=getint();
for(int re i=1;i<=m;++i){
int a=getint(),va=getint(),b=getint(),vb=getint();
edge[a+n*va].push_back(b+n*(1-vb));
edge[b+n*vb].push_back(a+n*(1-va));
}
if(_2_SAT()){
puts("POSSIBLE");
for(int re i=1;i<=n;++i){
printf("%d ",scc[i]<scc[i+n]);
}
}
else puts("IMPOSSIBLE");
return 0;
}