Katu Puzzle(2 - sat)

Katu Puzzle
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 7395   Accepted: 2720

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

X 0 = 1,  X 1 = 1,  X 2 = 0,  X 3 = 1.

       题意:

       给出 N (1 ~ 1000)和 M (0 ~ 1000000),代表有 N 个命题,M 条关系式。后给出 M 条关系式是什么。问能否找到一组命题的解,满足所有的关系式。

 

       思路:

       2 - sat。根据给出的关系式,将可以确定的关系进行建图。比如 a & b = 1,则 a == 1 -> b == 1,b == 1 -> a == 1,若 a == 0 或者 b == 0,则无论如何都不可能满足条件式,所以要把矛盾的条件也要进行建图,建图方法为 a == 0 -> a== 1,b == 0 -> b == 1。对 | 的情况也是如此,对于 ^ 则没有矛盾的情况。建图后判断一个命题的真和假有没有在同一个强连通分量即可。并且用 STL 的 vector 容器存邻接表。

 

      AC:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>

using namespace std;

const int NMAX = 1005 * 2;
const int EMAX = 1000000 * 2;

int n, m;
vector<int> v[NMAX];

int dfs_clock, scc_cnt;
int pre[NMAX], low[NMAX], cmp[NMAX];
stack<int> s;

void dfs(int u) {
        pre[u] = low[u] = ++dfs_clock;
        s.push(u);

        for (int i = 0; i < v[u].size(); ++i) {
                if (!pre[ v[u][i] ]) {
                        dfs( v[u][i] );
                        low[u] = min(low[u], low[ v[u][i] ]);
                } else if (!cmp[ v[u][i] ]) {
                        low[u] = min(low[u], pre[ v[u][i] ]);
                }
        }

        if (low[u] == pre[u]) {
                ++scc_cnt;
                for (;;) {
                        int x = s.top(); s.pop();
                        cmp[x] = scc_cnt;
                        if (x == u) break;
                }
        }
}

void scc() {
        dfs_clock = scc_cnt = 0;
        memset(pre, 0, sizeof(pre));
        memset(cmp, 0, sizeof(cmp));

        for (int u = 0; u < 2 * n; ++u) {
                if (!pre[u]) dfs(u);
        }
}

void add_edge (int a, int b, int ans, char *res) {
        if (!strcmp(res, "AND")) {
                if (!ans) {
                        v[a].push_back(n + b);
                        v[b].push_back(n + a);
                } else {
                        v[a].push_back(b);
                        v[b].push_back(a);
                        v[n + a].push_back(a); //矛盾情况
                        v[n + b].push_back(b); //矛盾情况
                }
        } else if (!strcmp(res, "OR")) {
                if (!ans) {
                        v[n + a].push_back(n + b);
                        v[n + b].push_back(n + a);
                        v[a].push_back(n + a); //矛盾情况
                        v[b].push_back(n + b); //矛盾情况
                } else {
                        v[n + a].push_back(b);
                        v[n + b].push_back(a);
                }
        } else if (!strcmp(res, "XOR")) {
                if (!ans) {
                        v[a].push_back(b);
                        v[b].push_back(a);
                        v[n + a].push_back(n + b);
                        v[n + b].push_back(n + a);
                } else {
                        v[a].push_back(n + b);
                        v[b].push_back(n + a);
                        v[n + a].push_back(b);
                        v[n + b].push_back(a);
                }
        }
}

int main() {

        scanf("%d%d", &n, &m);
        while (m--) {
                int a, b, ans;
                char res[5];
                scanf("%d%d%d%s", &a, &b, &ans, res);
                add_edge(a, b, ans, res);
        }

        scc();

        for (int i = 0; i < n; ++i) {
                if (cmp[i] == cmp[n + i]) {
                        printf("NO\n");
                        return 0;
                }
        }

        printf("YES\n");

        return 0;
}

  

 

 

 

你可能感兴趣的:(SA)