题目链接: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