[题解]POJ 3678 Katu Puzzle

【Description】

Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a boolean operator op (one of AND, OR, XOR) and an integer c (0 ≤ c ≤ 1). One Katu is solvable if one can find each vertex Vi a value Xi (0 ≤ Xi ≤ 1) such that for each edge e(a, b) labeled by op and c, the following formula holds:

 Xa op Xb = c

The calculating rules are:

AND 0 1
0 0 0
1 0 1
OR 0 1
0 0 1
1 1 1
XOR 0 1
0 0 1
1 1 0

Given a Katu Puzzle, your task is to determine whether it is solvable.

【Input】

The first line contains two integers N (1 ≤ N ≤ 1000) and M,(0 ≤ M ≤ 1,000,000) indicating the number of vertices and edges.
The following M lines contain three integers a (0 ≤ a < N), b(0 ≤ b < N), c and an operator op each, describing the edges.

【Output】

Output a line containing "YES" or "NO".

【Sample Input】

4 4
0 1 1 AND
1 2 1 OR
3 2 0 AND
3 0 0 XOR

【Sample Output】

YES

【Hint】

X0 = 1, X1 = 1, X2 = 0, X3 = 1.
-------------------------------------------------------------------------------------------------------------------------------------------
【题目大意】

n个布尔变量Xi,现在有m个约束条件,给出Xi op Xj = c,给出每个i j c 和 op。其中op可能是AND,OR,XOR。要求这n个布尔变量是否存在一组可能的取值,使得满足所有的约束条件。

【题解】
可以转化为一个2-SAT问题。每个变量拆成两个点i和i+n,i表示i==0,i+n表示i==1。
考虑建图:
op c Addedge
AND 0 i+n->j,j+n->i;
  1 i->i+n,j->j+n;
OR 0 i+n->i,j+n->j;
  1 i->j+n,j->i+n;
XOR 0 i+n->j+n.j->i,i->j,j+n->i+n;
  1 i->j+n,j->i+n,i+n->j,j+n->i;

细节参见代码:

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 #define MAXN 1020*2
  6 #define MAXM 1000020
  7 struct node
  8 {
  9     int v;
 10     node *next;
 11 };
 12 node edge[MAXN*MAXN];
 13 node *cnt=&edge[0];
 14 node *adj[MAXN];
 15 int n,m;
 16 int low[MAXN],dfn[MAXN],dcnt;
 17 int stack[MAXN],top;
 18 int Belong[MAXN],scc;
 19 bool Instack[MAXN];
 20 inline void Get_int(int &Ret)
 21 {
 22     char ch;
 23     bool flag=false;
 24     for(;ch=getchar(),ch<'0'||ch>'9';)
 25         if(ch=='-')
 26             flag=true;
 27     for(Ret=ch-'0';ch=getchar(),ch>='0'&&ch<='9';Ret=Ret*10+ch-'0');
 28     flag&&(Ret=-Ret);
 29 }
 30 inline void Addedge(int u,int v)
 31 {
 32     node *p=++cnt;
 33     p->v=v;
 34     p->next=adj[u];
 35     adj[u]=p;
 36 }
 37 void Read()
 38 {
 39     //Get_int(n);
 40     Get_int(m);
 41     int i,j,k,r;
 42     char cmd[8];
 43     for(k=1;k<=m;k++)
 44     {
 45         Get_int(i);i++;
 46         Get_int(j);j++;
 47         Get_int(r);
 48         scanf("%s",cmd);
 49         if(cmd[0]=='A')
 50         {
 51             if(!r)
 52             {
 53                 Addedge(i+n,j);
 54                 Addedge(j+n,i);
 55             }
 56             else
 57             {
 58                 Addedge(i,i+n);
 59                 Addedge(j,j+n);
 60             }
 61         }
 62         else if(cmd[0]=='O')
 63         {
 64             if(!r)
 65             {
 66                 Addedge(i+n,i);
 67                 Addedge(j+n,j);
 68             }
 69             else
 70             {
 71                 Addedge(i,j+n);
 72                 Addedge(j,i+n);
 73             }
 74         }
 75         else
 76         {
 77             if(!r)
 78             {
 79                 Addedge(i+n,j+n);
 80                 Addedge(j,i);
 81                 Addedge(i,j);
 82                 Addedge(j+n,i+n);
 83             }
 84             else
 85             {
 86                 Addedge(i,j+n);
 87                 Addedge(j,i+n);
 88                 Addedge(i+n,j);
 89                 Addedge(j+n,i);
 90             }
 91         }
 92     }
 93 }
 94 void Tarjan(int u)
 95 {
 96     int v;
 97     dfn[u]=low[u]=++dcnt;
 98     stack[++top]=u;
 99     Instack[u]=true;
100     for(node *p=adj[u];p;p=p->next)
101     {
102         v=p->v;
103         if(!dfn[v])
104         {
105             Tarjan(v);
106             low[u]=min(low[u],low[v]);
107         }
108         else if(Instack[v])
109             low[u]=min(low[u],dfn[v]);
110     }
111     if(low[u]==dfn[u])
112     {
113         scc++;
114         do
115         {
116             v=stack[top];
117             top--;
118             Instack[v]=false;
119             Belong[v]=scc;
120         }while(v!=u);
121     }
122 }
123 bool Work()
124 {
125     int i;
126     for(i=1;i<=n*2;i++)
127         if(!dfn[i])
128             Tarjan(i);
129     for(i=1;i<=n;i++)
130         if(Belong[i]==Belong[i+n])
131             return false;
132     return true;
133 }
134 void Print()
135 {
136     if(Work())
137         printf("YES\n");
138     else
139         printf("NO\n");
140 }
141 inline void Pre()
142 {
143     memset(edge,0,sizeof(edge));
144     cnt=&edge[0];
145     memset(adj,0,sizeof(adj));
146     memset(low,0,sizeof(low));
147     memset(dfn,0,sizeof(dfn));
148     dcnt=0;
149     memset(stack,0,sizeof(stack));
150     top=0;
151     memset(Belong,0,sizeof(Belong));
152     scc=0;
153     memset(Instack,false,sizeof(Instack));
154 }
155 int main()
156 {
157     while(scanf("%d",&n)!=EOF)
158     {
159         Pre();
160         Read();
161         Print();
162     }
163     return 0;
164 }

 

posted @ 2013-01-22 21:49  zyy是一只超级大沙茶  阅读(920)  评论(0)    收藏  举报