poj3678 Katu Puzzle

Posted zbtrs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj3678 Katu Puzzle相关的知识,希望对你有一定的参考价值。

Katu Puzzle
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 10239   Accepted: 3823

Description

Katu Puzzle is presented as a directed graph G(VE) 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 ≤ X≤ 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 (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.

Source

分析:每个数可以取0也可以取1,那么就是2-SAT问题!2-SAT问题最重要的就是建边,建边的关键是“必须”,也就是说,当a时,必须b,才从a连边到b,这道题涉及到自己到自己的反节点的连边,具体看代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stack>

using namespace std;

const int maxn = 1010 * 3,maxm = 2000010;

int n,m,head[maxn],top,to[maxm],nextt[maxm],tot = 1,dfs_clock,pre[maxn],low[maxn],scc[maxn];

stack <int> s;

void add(int x,int y)
{
    to[tot] = y;
    nextt[tot] = head[x];
    head[x] = tot++;    
} 

void tarjan(int u)
{
    pre[u] = low[u] = ++dfs_clock;
    s.push(u);
    for (int i = head[u];i; i = nextt[i])
    {
        int v = to[i];
        if (!pre[v])
        {
            tarjan(v);
            low[u] = min(low[u],low[v]);
        }
        else
        if (!scc[v])
        low[u] = min(low[u],pre[v]);
    }
    if (pre[u] == low[u])
    {
        top++;
        while (1)
        {
            int t = s.top();
            s.pop();
            scc[t] = top;
            if (t == u)
            break;
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i = 1; i <= m; i++)
    {
        int a,b,c;
        char op[5];
        scanf("%d%d%d",&a,&b,&c);
        scanf("%s",op);
        if (op[0] == A) //and
        {
            if (c == 1)
            {
                add(a + n,b + n);
                add(b + n,a + n);
                add(a,a + n); //a如果为0显然不能满足要求,所以a必须为1,所以从0连向1
                add(b,b + n);
            }
            else
            {
                add(a + n,b);
                add(b + n,a);
            }
        }
        if (op[0] == X)
        {
            if (c == 1)
            {
                add(a,b + n);
                add(a + n,b);
                add(b, a + n);
                add(b + n,a);
            }
            else
            {
                add(a,b);
                add(b,a);
                add(a + n,b + n);
                add(b + n,a + n);
            }
        }
        if (op[0] == O)
        {
            if (c == 1)
            {
                add(a,b + n);
                add(b,a + n);
            }
            else
            {
                add(a,b);
                add(b,a);
                add(a + n,a); //a,b必须全都为0才可以,选1后我们强行让它选0.
                add(b + n,b);
            }
        }
    }
    for (int i = 0; i <= 2 * n - 1; i++)
    if (!pre[i])
    tarjan(i);
    for (int i = 0; i < n; i++)
    if (scc[i] == scc[i + n])
    {
        printf("NO\n");
        return 0;
    } 
    printf("YES\n");
     
    return 0;
}

 

以上是关于poj3678 Katu Puzzle的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3678 Katu Puzzle

poj3678 Katu Puzzle

POJ3678 Katu Puzzle 2-sat

Poj3678:Katu Puzzle

[poj] 3678 Katu Puzzle

POJ 3678 Katu Puzzle