Party+hdu+简单2sat问题

来源:互联网 发布:金朝 知乎 编辑:程序博客网 时间:2024/04/27 21:40

Party

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4121    Accepted Submission(s): 1335


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
解决方案:可根据矛盾关系建立一个关系图,例如,对于夫妻A1,A1';A2,A2',若A1,A2有矛盾,则必须这样选择A1+A2'或A1'+A2.由这样的选择关系构成一个有向图,当发现一对夫妻的丈夫和妻子都出现在一个强联通图中时,则矛盾。
2sat问题的论证可看:
1)由对称性解2-SAT问题
2)赵爽的2-SAT解法浅析论文
code:
#include<iostream>#include<cstdio>#include<stack>#include<cstring>#define MMAX 1003using namespace std;int head[2*MMAX],k,N,M,index;int dfn[2*MMAX],low[2*MMAX],belong[2*MMAX],instack[2*MMAX];stack<int>S;struct edge{    int to;    int next;} E[2*MMAX*MMAX];void add(int from,int to){    E[k].to=to;    E[k].next=head[from];    head[from]=k++;}void init(){    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(instack,0,sizeof(instack));    for(int i=0; i<2*N; i++)    {        belong[i]=i;    }    index=1;    while(!S.empty())S.pop();}void tarjan(int u){    dfn[u]=low[u]=index++;    instack[u]=1;    S.push(u);    for(int v=head[u]; v!=-1; v=E[v].next)    {        int s=E[v].to;        if(!instack[s])        {            tarjan(s);            low[u]=min(low[u],low[s]);        }        else if(instack[s]==1) low[u]=min(low[u],dfn[s]);    }    if(dfn[u]==low[u]){        while(!S.empty()){            int temp=S.top();            belong[temp]=u;            S.pop();            instack[temp]=2;            if(temp==u) break;        }    }}int main(){    while(~scanf("%d%d",&N,&M))    {        init();        memset(head,-1,sizeof(head));        k=0;        for(int i=0; i<M; i++)        {            int d1,d2,hf1,hf2;            scanf("%d%d%d%d",&d1,&d2,&hf1,&hf2);            int u=2*d1+hf1;            int v=2*d2+hf2;            add(u,v^1);            add(v,u^1);        }        for(int i=0;i<2*N;i++){            if(!instack[i]){                tarjan(i);            }        }        bool flag=true;        for(int i=0;i<N;i++){            if(belong[2*i+1]==belong[2*i]){                flag=false;                break;            }        }        if(flag)            printf("YES\n");        else            printf("NO\n");    }    return 0;}

0 0
原创粉丝点击