Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 7395 | Accepted: 2720 |
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.
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
题意:
给出 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; }