题目大意:有n个数,刚开始都不知道是什么,有三种操作,
I p v: 第p个数等于v
I p q v: 第p个数^第q个数的结果为v
Q k p1 p2 p3 .. pk: 要求回答第p1个数到第p2个数的异或的结果
解题思路:还是像以往一样压缩路径,只不过压缩的时候要并上权,参考别人的思路的….
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 21020
int f[maxn], v[maxn], vis[maxn], a[maxn], T = maxn - 10;
void init(int n) {
for(int i = 0; i <= n + 1; i++) {
f[i] = i;
v[i] = 0;
vis[i] = 0;
}
f[T] = T, v[T] = 0;
}
int find(int x) {
if(x != f[x]) {
int tmp = f[x];
f[x] = find(f[x]);
v[x] ^= v[tmp];
}
return f[x];
}
int uset(int p, int q, int val) {
int r1 = find(p);
int r2 = find(q);
if(r1 == r2) {
if((v[p] ^ v[q]) != val)
return 0;
else
return 1;
}
if(r1 == T)
swap(r1,r2);
f[r1] = r2;
v[r1] = v[p] ^ v[q] ^ val;
return 1;
}
int main() {
int n, Q, p, q, val, mark = 1;
char ch[2], str[40];
while(scanf("%d%d", &n, &Q) == 2 && n + Q) {
init(n);
printf("Case %d:\n", mark++);
bool err = 0;
int facts = 0;
for(int i = 1; i <= Q; i++) {
scanf("%s", ch);
if(ch[0] == 'I') {
facts++;
gets(str);
if(sscanf(str,"%d%d%d", &p, &q, &val) == 2) {
val = q, q = T;
}
if(err)
continue;
if(!uset(p,q,val)) {
printf("The first %d facts are conflicting.\n", facts);
err = 1;
}
}
else {
int k , ans = 0;
scanf("%d", &k);
for(int i = 1; i <= k; i++) {
scanf("%d", &a[i]);
if(err)
continue;
int r = find(a[i]);
ans ^= v[a[i]];
a[i] = r;
vis[r] ^= 1;
}
if(err)
continue;
bool flag = 1;
for(int i = 1; i <= k; i++) {
if(vis[a[i]]) {
if(a[i] != T)
flag = 0;
}
vis[a[i]] = 0;
}
if(flag)
printf("%d\n", ans);
else
printf("I don't know.\n");
}
}
printf("\n");
}
return 0;
}