POJ 1733 Parity game

并查集

首先将 sum[l, r] 的奇偶性转换成 sum[1, l - 1] 和 sum[1, r] 的奇偶性是否相同
注意是 l - 1
然后维护并查集,有边带权和扩展域两种做法

边带权

若两数奇偶性相同,边权为 0 ,若不同,边权为 1 ,然后异或处理即可

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN = 20005;
int n, m, fa[MAXN], dis[MAXN], dat[MAXN], sub[MAXN], id[MAXN], tot;
struct po{
	int u, v, opt;
}a[MAXN];
char s[10];
int find(int x) {
	if(x != fa[x]) {
		int t = find(fa[x]);
		dis[x] ^= dis[fa[x]];
		fa[x] = t;
		return fa[x];
	}
	return fa[x];
}
int main() {
	cin >> m >> n;
	for(int i = 1; i <= n; i++) {
		cin >> a[i].u >> a[i].v >> s;
		if(s[0] == 'o') a[i].opt = 1;
		else a[i].opt = 0;
		++tot, sub[tot] = dat[tot] = a[i].u;
		++tot, sub[tot] = dat[tot] = a[i].v;
	}
	sort(sub + 1, sub + 1 + tot);
	tot = unique(sub + 1, sub + 1 + tot) - sub - 1;
	for(int i = 1; i <= n * 2; i++) {
		id[i] = lower_bound(sub + 1, sub + 1 + tot, dat[i]) - sub;
	}
	//for(int i = 1; i <= n * 2; i++) printf("%d %d\n", dat[i], id[i]);
	for(int i = 1; i <= tot; i++) fa[i] = i;
	for(int i = 1; i <= n; i++) {
		a[i].u = id[i * 2 - 1] - 1, a[i].v = id[i * 2];
		int r1 = find(a[i].u), r2 = find(a[i].v);
		//printf("%d %d\n", a[i].u, a[i].v);
		if(r1 != r2) {
			fa[r1] = r2;
			dis[r1] = a[i].opt ^ dis[a[i].u] ^ dis[a[i].v];
		}else {
			if((dis[a[i].u] ^ dis[a[i].v]) != a[i].opt) {printf("%d\n", i - 1);return 0;}
		}
	}
	/*for(int i = 1; i <= tot; i++) {
		printf("%d %d %d\n",i + 1, fa[i], dis[i]);
	}*/
	printf("%d\n", n);
	return 0;
}

扩展域

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN = 20005;
int n, m, fa[MAXN], dat[MAXN], sub[MAXN], id[MAXN], tot;
struct po{
	int u, v, opt;
}a[MAXN];
char s[10];
int find(int x) {
	if(x != fa[x]) return fa[x] = find(fa[x]);
	return fa[x];
}
void merge(int x, int y) {
	int r1 = find(x), r2 = find(y);
	if(r1 != r2){
		fa[r1] = r2;
	}
}
int main() {
	cin >> m >> n;
	for(int i = 1; i <= n; i++) {
		cin >> a[i].u >> a[i].v >> s;
		if(s[0] == 'o') a[i].opt = 1;
		else a[i].opt = 0;
		++tot, sub[tot] = dat[tot] = a[i].u;
		++tot, sub[tot] = dat[tot] = a[i].v;
	}
	sort(sub + 1, sub + 1 + tot);
	tot = unique(sub + 1, sub + 1 + tot) - sub - 1;
	for(int i = 1; i <= n * 2; i++) {
		id[i] = lower_bound(sub + 1, sub + 1 + tot, dat[i]) - sub;
	}
	tot++;
	//for(int i = 1; i <= n * 2; i++) printf("%d %d\n", dat[i], id[i]);
	for(int i = 1; i <= tot * 2; i++) fa[i] = i;
	for(int i = 1; i <= n; i++) {
		a[i].u = id[i * 2 - 1] - 1, a[i].v = id[i * 2];
		int u = a[i].u, v = a[i].v;
		if(a[i].opt) {
			if(find(u) == find(v)) {printf("%d\n", i - 1); return 0;}
			merge(u, v + tot);merge(v, u + tot);
		}else {
			if(find(u) == find(v + tot) || find(v) == find(u + tot)) {printf("%d\n", i - 1);return 0;}
			merge(u, v);merge(u + tot, v + tot);
		}
	}
	/*for(int i = 1; i <= tot; i++) {
		printf("%d %d %d\n",i + 1, fa[i], dis[i]);
	}*/
	printf("%d\n", n);
	return 0;
}
posted @ 2018-03-16 21:01  Mr_Wolfram  阅读(152)  评论(0编辑  收藏  举报