poj 3678 XOR和OR和AND(简单2-sat问题)

来源:互联网 发布:linux aria2 多线程 编辑:程序博客网 时间:2024/05/22 02:28
/*题意:给你一些边,每条边有一个值和一个运算符XOR OR  AND求是否存在一些点使得所有的边根据这些运算符可以符合条件的权值.建边方式参考:http://blog.csdn.net/shuangde800/article/details/8876533这种建边方式真好,以后就用这种了0 --  10 --  01 --  01 --  1根据预算符有矛盾就建两条边因为这题中的c只有两种取值0,1,所以只需要计算一次就可以了*/#include<stdio.h>#include<string.h>#include<stdlib.h>#include<algorithm>using namespace std;#define N  2100#define NN  1100000struct node{    int u,v,w,next;    char s[5];} bian[NN*8];int head[N],yong,low[N],dfn[N],belong[N],ans,top,index,stac[N],vis[N];void init(){    memset(head,-1,sizeof(head));    yong=index=ans=top=0;    memset(vis,0,sizeof(vis));    memset(dfn,0,sizeof(dfn));}void addedge(int u,int v){    bian[yong].v=v;    bian[yong].next=head[u];    head[u]=yong++;}void tarjan(int u){    low[u]=dfn[u]=++index;    stac[++top]=u;    vis[u]=1;    int i;    for(i=head[u]; i!=-1; i=bian[i].next)    {        int v=bian[i].v;        if(!dfn[v])        {            tarjan(v);            low[u]=min(low[u],low[v]);        }        else if(vis[v])            low[u]=min(low[u],dfn[v]);    }    if(low[u]==dfn[u])    {        ans++;        int t;        do        {            t=stac[top--];            belong[t]=ans;            vis[t]=0;        }        while(t!=u);    }}int slove(int n){    int i;    for(i=0; i<n*2; i++)        if(!dfn[i])            tarjan(i);    // printf("%d\n",ans);    for(i=0; i<n; i++)        if(belong[i]==belong[i+n])            return 0;    return 1;}int main(){    int n,m,i,u,v,w;    char s[5];    while(scanf("%d%d",&n,&m)!=EOF)    {        init();        for(i=0; i<m; i++)        {            scanf("%d%d%d%s",&u,&v,&w,s);            if(strcmp(s,"AND")==0)            {                if(w)                {                    addedge(u,v);                    addedge(v+n,u+n);//1,0                    addedge(u+n,v+n);                    addedge(v,u);//0,1                    addedge(u+n,v);                    addedge(v+n,u);//0,0                }                else                {                    addedge(u,v+n);                    addedge(v,u+n);                }            }            if(strcmp(s,"OR")==0)            {                if(w)                {                    addedge(u+n,v);                    addedge(v+n,u);                }                else                {                    addedge(u,v);                    addedge(v+n,u+n);//1,0                    addedge(u+n,v+n);                    addedge(v,u);//0,1                    addedge(u,v+n);                    addedge(v,u+n);//1,1                }            }            if(strcmp(s,"XOR")==0)            {                if(w)                {                    addedge(u+n,v);                    addedge(v+n,u);//0,0                    addedge(u,v+n);                    addedge(v,u+n);//1,1                }                else                {                    addedge(u,v);                    addedge(v+n,u+n);//1,0                    addedge(u+n,v+n);                    addedge(v,u);//0,1                }            }        }        if(slove(n))            printf("YES\n");        else            printf("NO\n");    }    return 0;}

0 0
原创粉丝点击