[HDU 4115]Eliminate Conflict[2-SAT]

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 999999

struct 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");
    }
}


你可能感兴趣的:([HDU 4115]Eliminate Conflict[2-SAT])