您的位置:首页 > 其它

HDU 4115 Eliminate the Conflict(2-sat)

2018-03-14 21:11 423 查看


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
, 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: