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:
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. 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
X
0 = 1,
X
1 = 1,
X
2 = 0,
X
3 = 1.
Source |
思路:
每个X要么是0,要么是1,很明显的2-sat模型,建好图之后直接用模板就行了。
根据这些结论建图:
AND 结果为1,则a、b!=0,结果为0,则a、b最多有一个为1;
OR 结果为1,则a、b至少有一个为1,结果为0,则a、b!=1;
XOR 结果为1,则a、b有且仅有一个为0,结果为0,则a、b全0或全1。
代码:
#include <cstdio>
#include <cstring>
#define maxn 2005
#define MAXN 4000005
using namespace std;
int n,m,num,flag;
int head[maxn];
int scc[maxn];
int vis[maxn];
int stack1[maxn];
int stack2[maxn];
struct edge
{
int v,next;
}g[MAXN];
void init()
{
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
memset(scc,0,sizeof(scc));
stack1[0] = stack2[0] = num = 0;
flag = 1;
}
void addedge(int u,int v)
{
num++;
g[num].v = v;
g[num].next = head[u];
head[u] = num;
}
void dfs(int cur,int &sig,int &cnt)
{
if(!flag) return;
vis[cur] = ++sig;
stack1[++stack1[0]] = cur;
stack2[++stack2[0]] = cur;
for(int i = head[cur];i;i = g[i].next)
{
if(!vis[g[i].v]) dfs(g[i].v,sig,cnt);
else
{
if(!scc[g[i].v])
{
while(vis[stack2[stack2[0]]] > vis[g[i].v])
stack2[0] --;
}
}
}
if(stack2[stack2[0]] == cur)
{
stack2[0] --;
++cnt;
do
{
scc[stack1[stack1[0]]] = cnt;
int tmp = stack1[stack1[0]];
if((tmp >= n && scc[tmp - n] == cnt) || (tmp < n && scc[tmp + n] == cnt))
{
flag = false;
return;
}
}while(stack1[stack1[0] --] != cur);
}
}
void Twosat()
{
int i,sig,cnt;
sig = cnt = 0;
for(i=0;i<n+n&&flag;i++)
{
if(!vis[i]) dfs(i,sig,cnt);
}
}
int main()
{
int i,j,a,b,c;
char s[10];
while(~scanf("%d%d",&n,&m))
{
init();
num=0;
for(i=0;i<m;i++)
{
scanf("%d%d%d%s",&a,&b,&c,s);
if(s[0]=='A')
{
if(c)
{
addedge(a,a+n);
addedge(b,b+n);
}
else
{
addedge(a+n,b);
addedge(b+n,a);
}
}
else if(s[0]=='O')
{
if(c)
{
addedge(a,b+n);
addedge(b,a+n);
}
else
{
addedge(a+n,a);
addedge(b+n,b);
}
}
else
{
if(c)
{
addedge(a,b+n);
addedge(b+n,a);
addedge(b,a+n);
addedge(a+n,b);
}
else
{
addedge(a,b);
addedge(b,a);
addedge(a+n,b+n);
addedge(b+n,a+n);
}
}
}
Twosat();
if(flag) printf("YES\n");
else printf("NO\n");
}
return 0;
}