[P4782]2-SAT问题
解题关键:2-sat模板,tarjan解决。
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; #define MAXN 2000006 #define MAXM 2000106 struct edge{ int to,nxt; }e[MAXM]; int head[MAXN],st[MAXN],dfn[MAXN],lowest[MAXN],belong[MAXN]; bool inst[MAXN]; int n,scnt,top,tot,m;//scnt从1开始 void init(){ memset(head,-1,sizeof head); scnt=top=tot=0; } void add_edge(int u, int v){ e[tot].to=v; e[tot].nxt=head[u]; head[u]=tot++; } void Tarjan(int u){ dfn[u]=lowest[u]=++tot; inst[u]=1; st[top++]=u; for(int i=head[u];i!=-1;i=e[i].nxt){ int v=e[i].to; if(!dfn[v]){ Tarjan(v); lowest[u]=min(lowest[u],lowest[v]); } else if(inst[v]){ lowest[u]=min(lowest[u],dfn[v]);//也可用lowest } } if(dfn[u]==lowest[u]){ scnt++; int t; do{ t=st[--top]; inst[t]=false; belong[t]=scnt; }while(t!=u); } } int main(){ init(); int a,x,b,y; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&a,&x,&b,&y); //左0右1 add_edge(a<<1|(x^1),b<<1|y);//一个假,一定推出来另一个真 add_edge(b<<1|(y^1),a<<1|x); } for(int i=2;i<=2*n+1;i++){ if(!dfn[i]) Tarjan(i); } for(int i=1;i<=n;i++){ if(belong[2*i]==belong[2*i+1]){ puts("IMPOSSIBLE"); return 0; } } puts("POSSIBLE"); //构造出的解 for(int i=1;i<=n;i++){ if(belong[2*i]<belong[2*i+1]) printf("0 "); else printf("1 "); } return 0; }