hdu 3234 异或(加权并查集)



有n(n<=20000)个未知的整数X0,X1,X2Xn-1,有以下Q个(Q<=40000)操作:

I p v :告诉你Xp=v

I p q v :告诉你Xp Xor Xq=v

Q k p1 p2 … pk : 询问 Xp1 Xor Xp2 .. Xor Xpk, k不大于15。

如果当前的I跟之前的有冲突的话,跳出

思路就是并查集的扩展,每个节点表示他与根结点的异或值 。。。。思路略

ps:忘打了个.导致wa了好长时间............跪了

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
using namespace std;
#define LL long long  

const LL maxn = 20000 + 5;
const LL INF = 1000000000;

LL x[maxn];
LL pa[maxn], num[maxn], n;//num数组记录每个集合中的元素个数 

void init() {              //增加了一个xn,即零结点
	for(LL i = 0; i <= n; i++) { pa[i] = i; x[i] = 0;}
}

LL find(LL id) {
	if(id != pa[id]) {
		LL tmp = pa[id];
		LL root = find(pa[id]);
		x[id] ^= x[tmp];
		return pa[id] = root;
	}
	else return id;
}

bool unio(LL p, LL q, LL v) {
	LL pap = find(p), paq = find(q);
	if(pap == paq) {
		return (x[p] ^ x[q]) == v;        //注意运算符的顺序,如果不加括号会错,位运算一定要小心优先级
	}
	if(pap == n) swap(pap, paq);
	pa[pap] = paq;
	x[pap] = x[p] ^ x[q] ^ v;   // 最重要的一步,将两颗树连接在一起,很巧妙;
	return true;
}

int main() {
	//freopen("input.txt", "r", stdin);
	LL Q, kase = 1;
	while(scanf("%lld%lld", &n, &Q) && n) {
		init();
		printf("Case %lld:\n", kase++);
		char cmd[2], str[20];
		LL facts = 0; bool flag = true;
		for(LL i = 1; i <= Q; i++) {
			if(!flag){ gets(str); continue;}
			scanf("%s", cmd);
			if(cmd[0] == 'I') {
				facts++;
				gets(str);
				LL p, q, v;
				if(sscanf(str, "%lld%lld%lld", &p, &q, &v) == 2) {
					v = q; q = n;
				}
				if(!unio(p, q, v)) {
					printf("The first %lld facts are conflicting.\n", facts);
					flag = false;
					continue;
				}
			}
			else {
				LL k, idp[20], tag = 1;
				LL ans = 0;
				scanf("%lld", &k);
				for(LL i = 0; i < k; i++) {
					scanf("%lld", &idp[i]);
					num[find(idp[i])] = 0;
				}
				for(LL i = 0; i < k; i++) {
					num[find(idp[i])]++;
					ans ^= x[idp[i]];
				}
				for(LL i = 0; i < k; i++) {
					if(num[find(idp[i])] % 2 == 1 && find(idp[i]) != n) {
						tag = 0; break;
					}
				}
				if(!tag) printf("I don't know.\n");
				else printf("%lld\n", ans);
			}
		}
		printf("\n");
	}
	return 0;
}
时间: 2024-12-15 04:12:16

hdu 3234 异或(加权并查集)的相关文章

HDU 3407.Zjnu Stadium 加权并查集

Zjnu Stadium Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3726    Accepted Submission(s): 1415 Problem Description In 12th Zhejiang College Students Games 2007, there was a new stadium built

HDU 2818 Building Block 加权并查集

Building Block                                                                      Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4548    Accepted Submission(s): 1408 Problem Description John

UVALive 4487 Exclusive-OR 加权并查集神题

已知有 x[0-(n-1)],但是不知道具体的值,题目给定的信息 只有 I P V,说明 Xp=V,或者 I P Q V,说明 Xp ^ Xq=v,然后要求回答每个询问,询问的是 某任意的序列值 Xp1^Xp2,,,,X^pk 这个题目用加权并查集是这么处理的: 1. f[]照样是代表父节点,照样进行路径压缩,把每个 V[i]=V[i]^V[f[i]],即节点存储的值实际是它与它父亲的异或的值.为什么要这样呢,因为异或首先满足交换律,而且异或同一个数偶数次,即相当于本身,那么这个题目的其中一个要

P1196 银河英雄传说(加权并查集)

P1196 银河英雄传说 题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山压 顶集团派宇宙舰队司令莱因哈特率领十万余艘战舰出征,气吞山河集团点名将杨 威利组织麾下三万艘战舰迎敌. 杨威利擅长排兵布阵,巧妙运用各种战术屡次以少胜多,难免恣生骄气.在 这次决战中,他将巴米利恩星域战场划分成30000列,每列依次编号为1, 2, …, 30000.之后

Zjnu Stadium(加权并查集)

Zjnu Stadium Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3186    Accepted Submission(s): 1226 Problem Description In 12th Zhejiang College Students Games 2007, there was a new stadium built

uva 12232 - Exclusive-OR(加权并查集)

题目链接:uva 12232 - Exclusive-OR 题目大意:有n个数,一开始并不知道具体的值,现在进行Q次操作. I u k:au的值为k I u v k:au?av=k Q k q1q2-qk:求q1?q2-?qk 对于Q操作不能确定的话输出"I don't know." 对于I操作矛盾的话则输出是第几条I操作出现矛盾的,并且停止后面所有的操作. 解题思路:加权并查集,f[x]表示x节点父亲节点,d[x]表示x节点与其父节点的亦或值,对于确定的节点值,可以将父亲节点设为0,

HDU 3635 延缓更新的并查集

Dragon Balls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2839    Accepted Submission(s): 1097 Problem Description Five hundred years later, the number of dragon balls will increase unexpecte

加权并查集——(POJ1988)Cube Stacking

Cube Stacking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 25647   Accepted: 8975 Case Time Limit: 1000MS Description Farmer John and Betsy are playing a game with N (1 <= N <= 30,000)identical cubes labeled 1 through N. They start w

HDU 3461 Code Lock(并查集的应用+快速幂)

* 65536kb,只能开到1.76*10^7大小的数组.而题目的N取到了10^7,我开始做的时候没注意,用了按秩合并,uset+rank达到了2*10^7所以MLE,所以貌似不能用按秩合并. 其实路径压缩也可以不用.............  题目的大意: 一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限

加权并查集

加权并查集是一种特殊的并查集,除可提供查询操作外,还可用于表示元素与其代表元素的关系.下面以食物链为例,讲解一下加权并查集. #include<cstdio> //调用cstdio库,使用getchar函数 #include<cctype> //调用cctype库,使用isdigit函数,返回参数是否为整数 int N,K,ans,r,x,y; //定义变量用于有几个动物,几句话,答案,以及动物的关系和两个要描述的动物 int f[50005],d[50005]; //定义数组记录