HDU 4115 Eliminate the Conflict
题意:Alice和Bob这对狗男女在玩剪刀石头布。已知Bob每轮要出什么,然后Bob给Alice一些限制,1表示i轮和j轮Alice必须出不一样的,0表示必须出一样的。假设Alice有一局输了就算输了,否则就是赢,问Alice能否赢
思路:2-sat问题,已经Bob出什么,Alice要么就出赢的要么就出平的,然后加上m个约束就是2-sat问题了
代码:
#include <cstdio> #include <cstring> #include <vector> using namespace std; const int N = 10005; int t, n, m, x[N], sn, S[N * 2]; vector<int> g[N * 2]; bool mark[N * 2]; void init() { for (int i = 0; i < 2 * n; i++) g[i].clear(); memset(mark, false, sizeof(mark)); } void add_edge(int u, int x, int v, int y) { u = u * 2 + x; v = v * 2 + y; g[u^1].push_back(v); g[v^1].push_back(u); } bool dfs(int u) { if (mark[u^1]) return false; if (mark[u]) return true; mark[u] = true; S[sn++] = u; for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (!dfs(v)) return false; } return true; } bool solve() { for (int i = 0; i < 2 * n; i += 2) { if (!mark[i] && !mark[i + 1]) { sn = 0; if (!dfs(i)) { for (int j = 0; j < sn; j++) mark[S[j]] = false; sn = 0; if (!dfs(i + 1)) return false; } } } return true; } int main() { int cas = 0; scanf("%d", &t); while (t--) { init(); scanf("%d%d", &n, &m); int tmp; for (int i = 0; i < n; i++) scanf("%d", &x[i]); int u, v, w; while (m--) { scanf("%d%d%d", &u, &v, &w); u--; v--; int tmp = 6 - x[u] - x[v]; int a = 6 - x[u] - tmp; int b = 6 - x[v] - tmp; int u1, u2, v1, v2; u2 = a > tmp; u1 = !u2; v2 = b > tmp; v1 = !v2; if (w == 1) { if (x[u] == x[v]) { add_edge(u, 1, v, 1); add_edge(u, 0, v, 0); } else add_edge(u, !u1, v, !v1); } else { if (x[u] == x[v]) { add_edge(u, 0, v, 1); add_edge(u, 1, u, 0); } else { add_edge(u, u1, u, u1); add_edge(v, v1, v, v1); } } } printf("Case #%d: %s\n", ++cas, solve() ?"yes" : "no"); } return 0; }