题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3062
2 1 0 1 1 1
YES
代码如下:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std ; #define M 4000017 #define N 100017 //a<<1 和 (a<<1) + 1。a<<1表示妻子,(a<<1) + 1表示丈夫 //连接某边是为了推出矛盾。x->y表示选x则必须选y //注意方向 struct node { int s, t; int nxt; } e[M]; int n, m; int idx, ans, tp, cont; int dfn[N],vis[N],low[N],head[N],st[N],belong[N]; void add(int s,int t) { e[cont].s = s; e[cont].t = t; e[cont].nxt = head[s]; head[s] = cont++; } void build_grap(int a, int b, int c, int d)//建图 { if(c==0 && d==0)//两个妻子 { add(a<<1, (b<<1)+1); add(b<<1, (a<<1) + 1); } else if(c==0 && d==1)//妻子和丈夫 { add((a<<1), (b<<1)); add((b<<1)+1, (a<<1)+1); } else if(c==1 && d==0)//丈夫和妻子 { add((a<<1) + 1, (b<<1) + 1); add(b<<1, a<<1); } else if(c==1 && d==1)//两个丈夫有矛盾 { add((a<<1)+1, b<<1); add((b<<1)+1, a<<1); } } void tarjan(int u) { dfn[u] = low[u] = ++idx; vis[u] = 1; st[++tp] = u; int v ; for(int i = head[u]; i != -1; i = e[i].nxt) { v = e[i].t ; if(!dfn[v]) { tarjan(v) ; low[u] = min(low[u],low[v]); } else if(vis[v]) low[u] = min(low[u],dfn[v]); } if(dfn[u] == low[u]) { ans++; while(1) { v = st[tp--]; vis[v] = 0; belong[v] = ans; if(v == u) break; } } } bool _2sat() { memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); idx = tp = ans = 0; for(int i = 0; i < 2*n; i++) if(!dfn[i]) tarjan(i) ; for(int i = 0; i < n; i++) if(belong[2*i]==belong[(2*i)^1])//矛盾 return false ; return true; } int main() { int a, b, c, d; while(~scanf("%d%d",&n,&m)) { cont = 0; memset(head,-1,sizeof(head)); for(int i = 0; i < m; i++) { scanf("%d%d%d%d",&a,&b,&c,&d); //int u, v; //u = a*2+c; v = b*2+d; //add(u, v^1); add(v, u^1); build_grap(a, b, c, d); } if(_2sat()) printf("YES\n"); else printf("NO\n"); } return 0 ; }
HDU 3062 Party(2-sat 模板题 tarjan )
原文地址:http://blog.csdn.net/u012860063/article/details/43375071