hdu 4115 2-SAT判定

思路:将每个回合的平手和赢最为一对对立状态。那么后面就是2-SAT判断了。

#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cstring>

#include<queue>

#include<map>

#define Maxn 20010

using namespace std;

map<int ,int> g[Maxn];

int vi[Maxn],head[Maxn],dfn[Maxn],low[Maxn],e,n,lab,top,num,id[Maxn],Stack[Maxn],wh[Maxn],hh[4][4];

struct Edge{

    int u,v,next;

}edge[100000];

void init()//初始化

{

    memset(vi,0,sizeof(vi));

    memset(head,-1,sizeof(head));

    memset(dfn,0,sizeof(dfn));

    memset(low,0,sizeof(low));

    memset(id,0,sizeof(id));

    for(int i=0;i<Maxn;i++)

        g[i].clear();

    e=lab=top=num=0;

}

void add(int u,int v)//加边

{

    edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;

}

void Tarjan(int u)//找出强连通分支

{

    int i,j,v;

    dfn[u]=low[u]=++lab;

    Stack[top++]=u;

    vi[u]=1;

    for(i=head[u];i!=-1;i=edge[i].next)

    {

        v=edge[i].v;

        if(!dfn[v])

        {

            Tarjan(v);

            low[u]=min(low[u],low[v]);

        }

        if(vi[v])

        low[u]=min(low[u],dfn[v]);



    }

    if(low[u]==dfn[u])

    {

        ++num;

        do{

            i=Stack[--top];

            vi[i]=0;

            id[i]=num;

        }while(i!=u);

    }

}

int solve()

{

    int i,j;

    for(i=1;i<=n;i++)

        if(!dfn[i])

            Tarjan(i);

    for(i=1;i<=n;i++)

        if(id[i]==id[i+n])

            return 0;

    return 1;

}

int main()

{

    int t,i,j,m,u,v,k,Case=0;

    hh[1][2]=hh[2][3]=hh[3][1]=1;

    scanf("%d",&t);

    while(t--){

        init();

        scanf("%d%d",&n,&m);

        for(i=1;i<=n;i++)

            scanf("%d",wh+i);

        int f=0;

        for(i=1;i<=m;i++){

            scanf("%d%d%d",&u,&v,&k);

            if(u>v)

                swap(u,v);

            if(g[u][v]==k+1||u==v&&k==0) continue;

            if(g[u][v]&&g[u][v]!=k+1||u==v&&k==1) {f=1;break;}

            g[u][v]=k+1;

            if(k==0){

              if(wh[u]==wh[v]){

                add(u,v);

                add(v+n,u+n);

                add(v,u);

                add(u+n,v+n);

              }else

              if(hh[wh[u]][wh[v]]){

                add(u,v+n);

                add(v,u+n);

                add(u+n,v);

                add(v+n,u);

                add(u+n,v+n);

                add(v,u);

              }

              else

              {

                add(u,v+n);

                add(v,u+n);

                add(u+n,v);

                add(v+n,u);

                add(u,v);

                add(v+n,u+n);

              }

            }

            else{

                if(wh[u]==wh[v]){

                    add(u,v+n);

                    add(v,u+n);

                    add(u+n,v);

                    add(v+n,u);

                }else

                if(hh[wh[u]][wh[v]]){

                    add(u,v);

                    add(v+n,u+n);

                }

                else{

                    add(u+n,v+n);

                    add(v,u);

                }

            }

        }

        printf("Case #%d: ",++Case);

        if(f){

            for(i++;i<=m;i++){

                scanf("%d%d%d",&u,&v,&k);

            }

            printf("no\n");

            continue;

        }

        if(solve())

            printf("yes\n");

        else

            printf("no\n");

    }

    return 0;

}

 

你可能感兴趣的:(HDU)