现在的位置: 首页 > 综合 > 正文

HDU 4115 Eliminate the Conflict(2-sat)

2018年10月11日 ⁄ 综合 ⁄ 共 1355字 ⁄ 字号 评论关闭

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;
}

抱歉!评论已关闭.