1. 程式人生 > >【模板】2—SAT問題

【模板】2—SAT問題

參考題目:洛谷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; }