[模板][P4782]2-SAT
阿新 • • 發佈:2019-03-02
() != int sin puts pos 問題 als con
Description:
有n個布爾變量\(x_1\)~\(x_n\),另有m個需要滿足的條件,每個條件的形式都是“\(x_i\)為true/false或\(x_j\)為true/false”。比如“\(x_1\)為真或\(x_3\)為假”、“\(x_7\)為假或\(x_2\)為假”。2-SAT 問題的目標是給每個變量賦值使得所有條件得到滿足。
Hint:
\(1\le n,m\le 10^6\)
Solution:
模板題,詳見代碼
#include <algorithm> #include <cmath> #include <stack> #include <cstdio> #include <cstdlib> #include <iostream> using namespace std; const int mxn=2e6+5; int n,m,tot,cnt,col; int hd[mxn],bl[mxn],dfn[mxn],low[mxn],ins[mxn]; stack<int > st; struct ed { int to,nxt; }t[mxn<<1]; inline void chkmax(int &x,int y) {if(x<y) x=y;} inline void chkmin(int &x,int y) {if(x>y) x=y;} inline void add(int u,int v) { t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt; } void tj(int u) { dfn[u]=low[u]=++tot; st.push(u); ins[u]=1; for(int i=hd[u];i;i=t[i].nxt) { int v=t[i].to; if(!dfn[v]) tj(v),chkmin(low[u],low[v]); else if(ins[v]) chkmin(low[u],dfn[v]); } if(dfn[u]==low[u]) { ++col; do{ bl[u]=col; u=st.top(); st.pop(); ins[u]=0; } while(low[u]!=dfn[u]); } } //tarjan基本操作,沒什麽好說的 int main() { scanf("%d%d",&n,&m); int u,v,x,y; for(int i=1;i<=m;++i) { scanf("%d%d%d%d",&u,&x,&v,&y); add(u+n*(x^1),v+n*y); add(v+n*(y^1),u+n*x); //建邊,很好懂的 } for(int i=1;i<=2*n;++i) if(!dfn[i]) tj(i); for(int i=1;i<=n;++i) if(bl[i]==bl[i+n]) { puts("IMPOSSIBLE"); return 0; } puts("POSSIBLE"); for(int i=1;i<=n;++i) printf("%d ",bl[i]>bl[i+n]); //按較大拓撲序輸出答案 return 0; }
[模板][P4782]2-SAT