HDOJ4115-Eliminate the Conflict,2SAT

来源:互联网 发布:中国最大数据公司 编辑:程序博客网 时间:2024/06/06 19:56

每一局alice要么与Bob平手,要么赢Bob,二取一,为2SAT问题,而不是锤子剪刀布3SAT。

对于m次要求,不管是same还是different,都分成三种情况,挺好想的2SAT。

#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int NN=25000;const int MM=100000;int n,m,en,head[NN],a[NN][2];struct Edge{    int v,next;    Edge() {}    Edge(int _v,int _next): v(_v),next(_next) {}} e[MM];void add(int u,int v){    e[en]=Edge(v,head[u]);    head[u]=en++;}int top,vn,bn,dfn[NN],low[NN],belong[NN],stack[NN];bool instack[NN];void tarjan(int u){    dfn[u]=low[u]=++vn;    stack[++top]=u;    instack[u]=1;    int v;    for (int i=head[u]; i!=-1; i=e[i].next)    {        v=e[i].v;        if (!dfn[v])        {            tarjan(v);            if (low[v]<low[u]) low[u]=low[v];        }        else if (instack[v] && dfn[v]<low[u])            low[u]=dfn[v];    }    if (low[u]==dfn[u])    {        bn++;        do        {            v=stack[top--];            instack[v]=0;            belong[v]=bn;        }while (v!=u);    }}bool two_sat(){    top=vn=bn=0;    for (int i=1; i<=2*n; i++) dfn[i]=0,instack[i]=0;    for (int i=1; i<=2*n; i++) if (!dfn[i]) tarjan(i);    for (int i=1; i<=n; i++) if (belong[i]==belong[i+n]) return 0;    return 1;}int main(){    int T,b,x,y,z,cas=0;    scanf("%d",&T);    while (T--)    {        en=0;        memset(head,-1,sizeof(head));        scanf("%d%d",&n,&m);        for (int i=1; i<=n; i++)        {            scanf("%d",&b);            b--;            a[i][0]=b; a[i][1]=(b+1)%3;        }        for (int i=1; i<=m; i++)        {            scanf("%d%d%d",&x,&y,&z);            if (z==0)            {                if (a[x][0]==a[y][0])                {                    add(x,y);                    add(x+n,y+n);                    add(y,x);                    add(y+n,x+n);                }                if (a[x][0]==a[y][1])                {                    add(x,y+n);                    add(x+n,x);                    add(y,y+n);                    add(y+n,x);                }                if (a[x][1]==a[y][0])                {                    add(x,x+n);                    add(x+n,y);                    add(y,x+n);                    add(y+n,y);                }            }            else            {                if (a[x][0]==a[y][0])                {                    add(x,y+n);                    add(x+n,y);                    add(y,x+n);                    add(y+n,x);                }                if (a[x][0]==a[y][1])                {                    add(x,y);                    add(y+n,x+n);                }                if (a[x][1]==a[y][0])                {                    add(x+n,y+n);                    add(y,x);                }            }        }        printf("Case #%d: ",++cas);        if (two_sat()) puts("yes");        else           puts("no");    }    return 0;}


原创粉丝点击