【uva12232/hdu3461】带权并查集维护异或值
题意:
对于n个数a[0]~a[n-1],但你不知道它们的值,通过逐步提供给你的信息,你的任务是根据这些信息回答问题:
I P V :告诉你a[P] = V
I P Q V:告诉你a[P] XOR a[Q] = V
Q K P1..PK:询问a[P1]^a[P2]^...a[PK]的值
n<=20000
题解:
首先看前两个操作:
第一个操作我们可以新加一个节点a[n]=0,则a[p]=val转化为a[p]^a[n]=val。
那么所有知道值的点必定都与a[n]在同一个并查集之内。
我们可以用带权并查集,对每个点x维护fa[x],d[x]是a[x]^a[fa[x]]。
对与第三个操作,我们可以发现p1,p2,...,pk必定在某几个并查集之中。
如果某个并查集中有奇数个p,那就相当于a[p1]^a[p2]^..a[px] ^ 奇数次a[根](异或一个数偶数次相当于没有异或它)。
如果根不是a[n],也就是根的值未知,那么必定是不确定答案的。
否则我们就可以直接算出。
注意合并的时候如果有一个是a[n]所在集合,要让a[n]为根。
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<ctime>
6 using namespace std;
7
8 const int N=20100;
9 int n,m,fa[N],d[N],cnt[N],q[N];
10 char s[10];
11
12 int findfa(int x)
13 {
14 if(fa[x]!=x)
15 {
16 int xx=fa[x];
17 fa[x]=findfa(fa[x]);
18 d[x]=d[x]^d[xx];
19 }
20 return fa[x];
21 }
22
23 int main()
24 {
25 freopen("a.in","r",stdin);
26 freopen("a.out","w",stdout);
27 char ch;
28 int x,y,k,p,xx,yy,val,ans,bk,ok,num,T=0;
29 while(1)
30 {
31 scanf("%d%d",&n,&m);
32 if(!n && !m) break;
33 printf("Case %d:\n",++T);
34 memset(cnt,0,sizeof(cnt));
35 for(int i=0;i<=n;i++) fa[i]=i,d[i]=0;
36 num=0;bk=1;
37 for(int i=1;i<=m;i++)
38 {
39 scanf("%s",s);
40 if(s[0]=='I')
41 {
42 num++;
43 scanf("%d%d%c",&x,&y,&ch);
44 if(ch==' ') scanf("%d",&val);
45 else val=y,y=n;
46 if(!bk) continue;
47 xx=findfa(x);yy=findfa(y);
48 if(xx!=yy)
49 {
50 if(xx==n) swap(x,y),swap(xx,yy);//debug
51 fa[xx]=y;
52 d[xx]=val^d[x];
53 }
54 else if((d[x]^d[y])!=val) {printf("The first %d facts are conflicting.\n",num);bk=0;}
55 }
56 else
57 {
58 scanf("%d",&k);
59 for(int j=1;j<=k;j++)
60 {
61 scanf("%d",&q[j]);
62 findfa(q[j]);
63 cnt[fa[q[j]]]++;
64 }
65 if(!bk) continue;
66 ans=0;ok=1;
67 for(int j=1;j<=k;j++)
68 {
69 x=q[j];
70 if(fa[x]!=n && (cnt[fa[x]]&1)) {printf("I don't know.\n");ok=0;break;}
71 ans^=d[x];
72 }
73 for(int j=1;j<=k;j++) cnt[fa[q[j]]]--;
74 if(ok) printf("%d\n",ans);
75 }
76 // printf("i = %d\n",i);
77 // for(int j=0;j<n;j++) printf("%d fa = %d d = %d\n",j,fa[j],d[j]);
78 // printf("\n");
79 }
80 printf("\n");
81 }
82 return 0;
83 }