HDU 3678 2-SAT

来源:互联网 发布:手机淘宝关闭智能联想 编辑:程序博客网 时间:2024/06/17 04:12
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>using namespace std;const int maxn = 2e5 + 10;int n, m, a, b, c;char s[100];int DFN[maxn], vis[maxn], low[maxn], Stack[maxn * 10], Belong[maxn], top, tol, cnt;vector<int> e[maxn];void Tarjan(int u){DFN[u] = low[u] = ++tol;vis[u] = true;Stack[++top] = u;int l = e[u].size();for (int i = 0; i < l; i++){int v = e[u][i];if (!DFN[v]){Tarjan(v);low[u] = min(low[u], low[v]);}else if (vis[v] && DFN[v] < low[u]) low[u] = DFN[v];}if (DFN[u] == low[u]){cnt++; int v;do{v = Stack[top--];vis[v] = false;Belong[v] = cnt;}while (v != u);}}bool TwoSat(int n){for (int i = 0; i < 2 * n; i++)if (!DFN[i]) Tarjan(i);for (int i = 0; i < n; i++)if (Belong[2 * i] == Belong[2 * i + 1]) return false;return true;}int main(int argc, char const *argv[]){scanf("%d%d", &n, &m);for (int i = 0; i < m; i++){scanf("%d%d%d%s", &a, &b, &c, s);if (s[0] == 'A'){if (c){e[2 * a + 1].push_back(2 * a);e[2 * b + 1].push_back(2 * b);}else{e[2 * a].push_back(2 * b + 1);e[2 * b].push_back(2 * a + 1);}}else if (s[0] == 'O'){if (c){e[2 * a + 1].push_back(2 * b);e[2 * b + 1].push_back(2 * a);}else{e[2 * a].push_back(2 * a + 1);e[2 * b].push_back(2 * b + 1);}}}printf("%s\n", (TwoSat(n) ? "YES" : "NO"));return 0;}


有一个有向图G(V,E),每条边e(a,b)上有一个位运算符op(AND, OR或XOR)和一个值c(0或1)。
问能不能在这个图上的每个点分配一个值X(0或1),使得每一条边e(a,b)满足  Xa op Xb =  c

对于两个点a和 b,   a有两个值a1=0,a2=1, b也有两个值 b1=0, b2=1.
那么枚举这两点的所有关系(a1, b1)(a1, b2)(a2, b1)(a2, b2)
然后根据位运算符看每个关系时符合条件还是不符合,如果不符合就说明这个关系时矛盾对,要添加两条边
假设是关系(a1,b1)矛盾,那么就要添加边  a1—>b2,  b1—>a2即可。

0 0
原创粉丝点击