zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    ", i - 1);return 0;}
    		}
    	}
    	/*for(int i = 1; i <= tot; i++) {
    		printf("%d %d %d
    ",i + 1, fa[i], dis[i]);
    	}*/
    	printf("%d
    ", 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
    ", 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
    ", 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
    ", i - 1);return 0;}
    			merge(u, v);merge(u + tot, v + tot);
    		}
    	}
    	/*for(int i = 1; i <= tot; i++) {
    		printf("%d %d %d
    ",i + 1, fa[i], dis[i]);
    	}*/
    	printf("%d
    ", n);
    	return 0;
    }
    
  • 相关阅读:
    一文了解网络编程之走进TCP三次握手和HTTP那些你不知道的事
    并发编程面试必备之ConcurrentHashMap源码解析
    java延迟队列DelayQueue及底层优先队列PriorityQueue实现原理源码详解
    聊一聊面试中常问的延时队列
    面试必备HashMap源码解析
    synchronized解锁源码分析
    synchronized的jvm源码加锁流程分析聊锁的意义
    jvm源码解析java对象头
    从ReentrantLock源码入手看锁的实现
    从synchronized和lock区别入手聊聊java锁机制
  • 原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8585245.html
Copyright © 2011-2022 走看看