您的位置:首页 > 其它

poj3678 Katu Puzzle 【解法一】

2016-08-04 13:40 197 查看
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”.

解法二见【这里】

2-SAT模板题。

把每个点拆成选和不选,然后用每个条件相互连边。

比如a&b=0就是a=1->b=0,b=1->a=0,也就是说连边表示由起点这个状态能推导出终点的状态。

比较特殊的是a&b=1和a|b=0,这就不是推导关系了,而是已经确定的元素。这里需要特殊判断一下。

然后在图上进行dfs,直到所有点都被标记为止。需要注意的是不需要回溯,也就是如果某一个点无论取1还是0都失败了,那就不用再回去更改之前的值,直接宣告失败即可。

#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
vector<int> to[2010];
stack<int> sta;
int m,n;
bool b[2010],vis,must[2010];
void init()
{
int i,j,k,x,y,z;
char s[5];
scanf("%d%d",&n,&m);
for (i=1;i<=m;i++)
{
scanf("%d%d%d%s",&x,&y,&z,s+1);
if (s[1]=='A')
{
if (z==1) must[2*x]=must[2*y]=1;
else
{
to[2*x].push_back(2*y+1);
to[2*y].push_back(2*x+1);
}
}
if (s[1]=='O')
{
if (z==0) must[2*x+1]=must[2*y+1]=1;
else
{
to[2*x+1].push_back(2*y);
to[2*y+1].push_back(2*x);
}
}
if (s[1]=='X')
{
if (z==1)
{
to[2*x].push_back(2*y+1);
to[2*x+1].push_back(2*y);
to[2*y].push_back(2*x+1);
to[2*y+1].push_back(2*x);
}
else
{
to[2*x+1].push_back(2*y+1);
to[2*x].push_back(2*y);
to[2*y+1].push_back(2*x+1);
to[2*y].push_back(2*x);
}
}
}
}
bool dfs(int x)
{
if (b[x^1]||must[x^1]) return 0;
if (b[x]) return 1;
b[x]=1;
sta.push(x);
for (int i=0;i<to[x].size();i++)
if (!dfs(to[x][i])) return 0;
return 1;
}
bool solve()
{
int i,j,k,x,y,z;
for (i=0;i<n;i++)
{
if (!must[i*2+1]&&dfs(i*2)) continue;
while (!sta.empty())
{
b[sta.top()]=0;
sta.pop();
}
if (must[i*2]||!dfs(i*2+1)) return 0;
}
return 1;
}
int main()
{
init();
if (solve()) printf("YES\n");
else printf("NO\n");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  2-SAT dfs