[HDU 4115]Eliminate Conflict[2-SAT]

来源:互联网 发布:wap淘宝是哪里进来流量 编辑:程序博客网 时间:2024/06/05 07:33

http://www.cnblogs.com/ambition/archive/2011/11/09/Eliminate_the_Conflict.html


题意:

两个人石头剪刀布,一个人的出法是确定的,另一个人的出法有一定约束,某两次要相同或者不同,问你第二个人能否全部都不失败。

思路:

拆成六个点:

石头(R), 非石头(~R)

    布(P), 非布(~P)

剪刀(S), 非剪刀(~S)

1. 每次只能三者取一个,那么就是如果出了一个,另外两个就不能出

R->~P, R->~S, P->~R, P->~S, S->~R, S->~P

2. 根据对方的出法,只能出平局和胜局两种出法

比如:如果对方是石头(R),那么只能出R和P,非R即P,非P即R

~R->P, ~P->R

3. 加入约束关系,如果两次必须相同:

R1<->R2, P1<->P2, S1<->S2 均是双向边

如果不同也是一样

R1->~R2, R2->~R1, ......

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 60005#define M 999999struct Edge{    int vtx,next;}E[M];int head[N],size;int dfn[N],low[N],blg[N],step,scc;int stk[N],top;bool ins[N];void Init(){    memset(head,-1,sizeof(head));    memset(dfn,-1,sizeof(dfn));    memset(ins,false,sizeof(ins));    step=size=0; top=-1;}void Insert(int u,int v){    E[size].vtx=v;    E[size].next=head[u];    head[u]=size++;}void Tarjan(int u){    stk[++top]=u; ins[u]=true;    dfn[u]=low[u]=step++;    for(int i=head[u];~i;i=E[i].next){        int v=E[i].vtx;        if(dfn[v]==-1){            Tarjan(v);            low[u]=min(low[u],low[v]);        }else if(ins[v]){            low[u]=min(low[u],dfn[v]);        }    }    if(low[u]==dfn[u]){        for(int v=-1;v!=u;top--){            v=stk[top];            ins[v]=false;            blg[v]=scc;        }        scc++;    }}int main(){    int t,cas=0;    scanf("%d",&t);    while(t--){        int n,m;        scanf("%d%d",&n,&m);        /*build*/        Init();        for(int i=0;i<n;i++){            Insert(i*6+0,i*6+3);            Insert(i*6+0,i*6+5);            Insert(i*6+2,i*6+1);            Insert(i*6+2,i*6+5);            Insert(i*6+4,i*6+1);            Insert(i*6+4,i*6+3);        }        for(int i=0;i<n;i++){            int v;            scanf("%d",&v);            if(v==1){                Insert(i*6+3,i*6+0);                Insert(i*6+1,i*6+2);            }else if(v==2){                Insert(i*6+5,i*6+2);                Insert(i*6+3,i*6+4);            }else if(v==3){                Insert(i*6+5,i*6+0);                Insert(i*6+1,i*6+4);            }        }        for(int i=0;i<m;i++){            int a,b,v;            scanf("%d%d%d",&a,&b,&v);            a--; b--;            if(v){                Insert(a*6+0,b*6+1);                Insert(a*6+2,b*6+3);                Insert(a*6+4,b*6+5);                Insert(b*6+0,a*6+1);                Insert(b*6+2,a*6+3);                Insert(b*6+4,a*6+5);            }else{                Insert(a*6+0,b*6+0);                Insert(a*6+2,b*6+2);                Insert(a*6+4,b*6+4);                Insert(b*6+0,a*6+0);                Insert(b*6+2,a*6+2);                Insert(b*6+4,a*6+4);            }        }        /*2-SAT*/        for(int i=0;i<n*6;i++){            if(dfn[i]==-1) Tarjan(i);        }        bool flag=true;        for(int i=0;i<n*3;i++){            if(blg[i<<1]==blg[i<<1|1]){                flag=false;                break;            }        }        printf("Case #%d: ",++cas);        puts(flag?"yes":"no");    }}


原创粉丝点击