Katu Puzzle

poj3678:http://poj.org/problem?id=3678

题意:给你一些数,然后这些要么是0要么是1,然后回给出一些数之间的and,or,xor的值,问你是否存在一组解。

题解:2-sat的一道很好的题目。能很好训练建边的思想。建边如下。

and==1: 说明 a,b必须选,就是必须都是1,所以a->~a,b->~b;

ans==0,说明 a,b不能同时都选,那么选择了~a就只能选择b,选择了~b就只能选择a;所以有边,~a-->b,~b->a;

or==1说明至少有一个是1 ,至少取一个,a-->~b;b-->~a;

or==0说明都不取, ~a->a;~b->b;

xor==1建边 x->~y,y->~x,~y->x,~x->y (两个数必须不同)

xor==0 建边 x->y,y->x,~x->~y,~y->~x (两个数必须相同)

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 const int N=1e5+10;
  7 const int M=1e7+100;
  8 struct Edge{
  9     int to,next;
 10 } edge[M];
 11 int  n,m,cnt,dep,top,atype;
 12 int  dfn[N],low[N],vis[N],head[N],st[N],belong[N],in[N],out[N],sum[N];
 13 //sum[i]记录第i个连通图的点的个数,in[i],out[i],表示缩点之后点的入度和初度。
 14 void init(){
 15       cnt=dep=top=atype=0;
 16     memset(head,-1,sizeof(head));
 17     memset(dfn,0,sizeof(dfn));
 18     memset(low,0,sizeof(low));
 19     memset(vis,0,sizeof(vis));
 20     memset(belong,0,sizeof(belong));
 21     memset(in,0,sizeof(in));
 22     memset(out,0,sizeof(out));
 23     memset(sum,0,sizeof(sum));
 24 }
 25 void addedge(int u,int v){
 26     edge[cnt].to=v;
 27     edge[cnt].next=head[u];
 28     head[u]=cnt++;
 29 }
 30 
 31 void Tarjan(int u){
 32     dfn[u]=low[u]=++dep;
 33     st[top++]=u;
 34     vis[u]=1;
 35     for(int i=head[u]; i!=-1; i=edge[i].next){
 36         int v=edge[i].to;
 37         if(!dfn[v]){
 38             Tarjan(v);
 39             low[u]=min(low[u],low[v]);
 40         }
 41         else if(vis[v]){
 42             low[u]=min(low[u],dfn[v]);
 43         }
 44     }
 45     int j;
 46     if(dfn[u]==low[u]){
 47         atype++;
 48         do{
 49             j=st[--top];
 50             belong[j]=atype;
 51             sum[atype]++;   //记录每个连通分量中点的个数
 52             vis[j]=0;
 53         }
 54         while(u!=j);
 55     }
 56 }
 57 char str[23];
 58 int u,v,w;
 59 int main(){
 60   while(~scanf("%d%d",&n,&m)){
 61         init();
 62       for(int i=1;i<=m;i++){
 63         scanf("%d%d%d%s",&u,&v,&w,str);
 64           u++;v++;
 65          if(str[0]=='A'){
 66             if(w==1){
 67                 addedge(u,u+n);
 68                 addedge(v,v+n);
 69             }
 70             else{
 71                 addedge(u+n,v);
 72                 addedge(v+n,u);
 73             }
 74          }
 75          else if(str[0]=='O'){
 76             if(w==1){
 77             addedge(u,v+n);
 78             addedge(v,u+n);
 79             }
 80             else {
 81                 addedge(u+n,u);
 82                 addedge(v+n,v);
 83             }
 84          }
 85          else if(str[0]=='X'){
 86             if(w==1){
 87               addedge(u,v+n);
 88               addedge(u+n,v);
 89               addedge(v+n,u);
 90               addedge(v,u+n);
 91             }
 92             else{
 93                 addedge(u,v);
 94                 addedge(v,u);
 95                 addedge(u+n,v+n);
 96                 addedge(v+n,u+n);
 97             }
 98          }
 99       }
100       for(int i=1;i<=2*n;i++)
101         if(!dfn[i])Tarjan(i);
102       bool flag=false;
103       for(int i=1;i<=n;i++){
104           if(belong[i]==belong[i+n]){
105             flag=true;
106             break;
107           }
108       }
109       if(flag)printf("NO\n");
110       else
111         printf("YES\n");
112   }
113 }
View Code


 

 

posted on 2014-08-23 22:35  天依蓝  阅读(391)  评论(0编辑  收藏  举报

导航