首页 > 代码库 > poj 3678 XOR和OR和AND(简单2-sat问题)

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

/*
题意:给你一些边,每条边有一个值和一个运算符XOR OR  AND求是否存在一些点使得所有的边根据这些运算符
可以符合条件的权值.
建边方式参考:http://blog.csdn.net/shuangde800/article/details/8876533
这种建边方式真好,以后就用这种了
0 --  1
0 --  0
1 --  0
1 --  1
根据预算符有矛盾就建两条边
因为这题中的c只有两种取值0,1,所以只需要计算一次就可以了
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define N  2100
#define NN  1100000
struct 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;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;}

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