HDU 3062 Party(2-sat 模板题 tarjan )

来源:互联网 发布:sql安全性 编辑:程序博客网 时间:2024/05/21 22:49

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3062


Problem Description
有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n 个人同时列席?
 
Input
n: 表示有n对夫妻被邀请 (n<= 1000)
m: 表示有m 对矛盾关系 ( m < (n - 1) * (n -1))

在接下来的m行中,每行会有4个数字,分别是 A1,A2,C1,C2
A1,A2分别表示是夫妻的编号
C1,C2 表示是妻子还是丈夫 ,0表示妻子 ,1是丈夫
夫妻编号从 0 到 n -1
 
Output
如果存在一种情况 则输出YES
否则输出 NO
 
Sample Input
2 10 1 1 1
 
Sample Output
YES
 
Source
2009 Multi-University Training Contest 16 - Host by NIT 


代码如下:

#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 ;}


1 0
原创粉丝点击