1. 程式人生 > 其它 >UVa 12232 Exclusive-OR (帶權並查集)

UVa 12232 Exclusive-OR (帶權並查集)

題目連結:https://www.luogu.com.cn/problem/UVA12232

對於條件 \(p \oplus q = v\),將 \(p\) 所在並查集和 \(q\) 所在並查集合並,權值為 \(d[p] \oplus d[q]\oplus v\) 即可

對於條件 \(p = v\),建立一棵虛擬節點,值為 \(0\),按上面合併即可,注意要以虛擬節點為根

查詢需要保證每個並查集中需要查詢的值有偶數個(虛擬節點所在並查集除外,因為虛擬節點值已知),否則不知道值是多少

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 40010;

int n, Q;
int fa[maxn], d[maxn];
int nod[maxn], cnt[maxn];
char s[100];

int find(int x){
	if(fa[x] != x) {
		int rt = find(fa[x]);
		d[x] ^= d[fa[x]];
		return fa[x] = rt;
	}
	else return x;
}

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	int kase = 0;
	while(scanf("%d%d", &n, &Q) && n){
		printf("Case %d:\n", ++kase);
		int tot = 0;
		for(int i = 0 ; i <= n ; ++i) fa[i] = i, d[i] = 0, cnt[i] = 0;
		int p, q, val, k;
		int omit = 0;
		for(int i = 1 ; i <= Q ; ++i){
			scanf("%s", s);
			if(s[0] == 'I'){
				++tot;
				gets(s);
				if(sscanf(s, "%d%d%d", &p, &q, &val) == 2){
					val = q;
					q = n;
				}
				
				if(omit) continue;
				
				int u = find(p), v = find(q);
				
				if(u == v){
					if((d[p] ^ d[q]) != val){
						printf("The first %d facts are conflicting.\n", tot);
						omit = 1;						
					}
				} else{
					if(u == n) swap(u, v); // 以虛擬節點作為根,方便後續查詢 
					fa[u] = v;
					d[u] = (d[p] ^ d[q] ^ val);
				}
			} else{
				scanf("%d", &k);
				vector<int> rt;
				rt = vector<int>();
				int ans = 0;
				for(int j = 1 ; j <= k ; ++j) {
					scanf("%d", &nod[i]); 
					int u = find(nod[i]);
					rt.push_back(u);
					cnt[u] ^= 1;
					ans ^= d[nod[i]];
				}
				
				if(omit) continue;
				
				int flag = 0;
				for(auto u : rt) {
					if((cnt[u] & 1) && (u != n)) {
						flag = 1;
						printf("I don't know.\n");
						break;
					}
				}
				if(!flag) {
					printf("%d\n", ans);
				} 
				for(auto u : rt) cnt[u] = 0;
			}
		}
		printf("\n"); 
	}
	return 0;
}