UVA 12232 - Exclusive-OR(带权并查集)

UVA 12232 - Exclusive-OR

题目链接

题意:有n个数字。一開始值都不知道,每次给定一个操作,I a v表示确认a值为v,I a b v,表示确认a^b = v,Q k a1 a2 a3 ... ak。表示推断这些数字的异或值是否能确定。能确定就输出值,假设有矛盾就停止

思路:带权并查集,权表示和父结点的异或值,那么多数推断的时候,仅仅要全部数字和他的父结点的异或值的异或值。假设父结点的个数是偶数个。那么依据异或的性质能抵消掉,是能够判定的。假设不为偶数,就是不能判定。

注意第一种操作,要加个小处理,就是多一个虚拟结点,保证虚拟结点始终为根。虚拟结点代表0。这样仅仅要连到虚拟结点上。第一种和另外一种操作事实上就是一样的了

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 20005;

int n, qn, parent[N], val[N], vis[N];
struct query {
    char c;
    int a, b, v, k, x[20];
} q[2 * N];

int find(int x) {
    if (x == parent[x]) return x;
    int tmp = parent[x];
    parent[x] = find(parent[x]);
    val[x] ^= val[tmp];
    return parent[x];
}

void init() {
    for (int i = 0; i <= n; i++) {
	parent[i] = i;
	val[i] = 0;
    }
    char Q[105];
    for (int i = 0; i < qn; i++) {
	scanf("%s", Q);
	q[i].c = Q[0];
	int a, b, v;
	if (Q[0] == 'I') {
	    gets(Q);
	    if (sscanf(Q, "%d%d%d", &a, &b, &v) == 2) {
		v = b; b = n;
	    }
	    q[i].a = a; q[i].b = b; q[i].v = v;
	}
	else {
	    scanf("%d", &q[i].k);
	    for (int j = 0; j < q[i].k; j++)
		scanf("%d", &q[i].x[j]);
	}
    }
}

void solve() {
    int fir = 0;
    for (int i = 0; i < qn; i++) {
	if (q[i].c == 'I') {
	    fir++;
	    int pa = find(q[i].a);
	    int pb = find(q[i].b);
	    if (pa == n) swap(pa, pb);
	    if (pa == pb) {
		if ((val[q[i].a]^val[q[i].b]) != q[i].v) {
		    printf("The first %d facts are conflicting.\n", fir);
		    return;
		}
	    }
	    else {
		parent[pa] = pb;
		val[pa] = val[q[i].a]^val[q[i].b]^q[i].v;
	    }
	}
	else {
	    int ans = 0;
	    for (int j = 0; j < q[i].k; j++) {
		int px = find(q[i].x[j]);
		ans ^= val[q[i].x[j]];
		if (px != n)
		    vis[px] ^= 1;
	    }
	    int flag = 1;
	    for (int j = 0; j < q[i].k; j++) {
		if (vis[parent[q[i].x[j]]])
		    flag = 0;
		vis[parent[q[i].x[j]]] = 0;
	    }
	    if (flag) printf("%d\n", ans);
	    else printf("I don't know.\n");
	}
    }
}

int main() {
    int cas = 0;
    while (~scanf("%d%d", &n, &qn) && n) {
	init();
	printf("Case %d:\n", ++cas);
	solve();
	printf("\n");
    }
    return 0;
}
时间: 2024-10-17 17:22:49

UVA 12232 - Exclusive-OR(带权并查集)的相关文章

UVA 3027 Corporative Network 带权并查集、

题意:一个企业要去收购一些公司把,使的每个企业之间互联,刚开始每个公司互相独立 给出n个公司,两种操作 E I:询问I到I它连接点最后一个公司的距离 I I J:将I公司指向J公司,也就是J公司是I公司的上级,距离为abs(I-J)%1000(貌似G++不支持abs,PE了两发) 思路:转化一下题意就行了,首先刚开始的时候每个公司都是独立的,I操作就是并查集中合并操作,将I这课树并到J这个树上, E操作要求的东西就是 I到I的根节点的距离,先看一个没有路径压缩直接暴力的方法把.(本以为不会过的,

UVA - 10004 Bicoloring(判断二分图——交叉染色法 / 带权并查集)

d.给定一个图,判断是不是二分图. s.可以交叉染色,就是二分图:否则,不是. 另外,此题中的图是强连通图,即任意两点可达,从而dfs方法从一个点出发就能遍历整个图了. 如果不能保证从一个点出发可以遍历整个图,那么编程要注意了,应该从每个点出发遍历一次. s2.带权并查集来判断,略复杂.先略过.先上个博客:http://blog.csdn.net/zsc09_leaf/article/details/6727622 c.邻接矩阵,bfs #include<iostream> #include&

hdu3038(带权并查集)

题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 题意: n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示从第x,个元素到第y个元素的和为d(包括x, 和y), 问m行输入里面有几个是错误的(第一个输入是正确的); 思路: 很显然带权并查集咯,我们可以用距离的概念代替和的概念比较好理解一点,d表示x到y的和即x到y的距离; 可以用rank[x]表示x到其父亲节点的距离,  将正确的距离关系合并到并查集中

【POJ1182】 食物链 (带权并查集)

Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之

【poj 1988】Cube Stacking(图论--带权并查集 模版题)

题意:有N个方块,M个操作{“C x”:查询方块x上的方块数:“M x y”:移动方块x所在的整个方块堆到方块y所在的整个方块堆之上}.输出相应的答案. 解法:带权并查集.每堆方块作为一个集合,维护3个数组:fa[x]表示x方块所在堆的最顶部的方块:d[x]表示x方块所在堆的最底部的方块:f[x]表示x方块方块x上的方块数. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<

并查集练习2(带权并查集)

明天旅游去爬山逛庙玩,今天练一天然后早早睡觉啦~ poj1703 Find them, Catch them (带权并查集) 1 #include<cstdio> 2 const int N=1e5+1; 3 int f[N]; 4 int r[N];//表示与父节点的关系,0同类,1不同类 5 int n; 6 void init(){ 7 for(int i=1;i<=n;++i){ 8 f[i]=i; r[i]=0; 9 } 10 } 11 int fin(int x){ 12 i

Lightoj1009 Back to Underworld(带权并查集)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Back to Underworld Time Limit:4000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Description The Vampires and Lykans are fighting each other to death. The war has become so fierc

[NOIP摸你赛]Hzwer的陨石(带权并查集)

题目描述: 经过不懈的努力,Hzwer召唤了很多陨石.已知Hzwer的地图上共有n个区域,且一开始的时候第i个陨石掉在了第i个区域.有电力喷射背包的ndsf很自豪,他认为搬陨石很容易,所以他将一些区域的陨石全搬到了另外一些区域. 在ndsf愉快的搬运过程中,Hzwer想知道一些陨石的信息.对于Hzwer询问的每个陨石i,你必须告诉他,在当前这个时候,i号陨石在所在区域x.x区域共有的陨石数y.以及i号陨石被搬运的次数z. 输入描述: 输入的第一行是一个正整数T.表示有多少组输入数据. 接下来共有

hdu 1558 Segment set【基础带权并查集+计算几何】

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3599    Accepted Submission(s): 1346 Problem Description A segment and all segments which are connected with it compose a segment set