pku 1703(种类并查集)

题目链接:http://poj.org/problem?id=1703

思路;个人觉得本质上还是和带权并查集一样的,只不过多了一个MOD操作,然后就是向量关系图稍微改动一下就变成种类并查集了,对于本题,我们可以用一个kind数组来表示是否属于同一类,其中kind[x]==0表示不是同一类,kind[x]==1表示属于同一类,这样我们就可以得到向量关系式了(若r1=Find(u),r2=Find(v),并且parent[r1]=r2,那么就有kind[v]+1==kind[u]+kind[r1])然后变形后对2取余就可以了,即kind[r1]=(kind[v]-kind[u]+1)%2,这是Union部分,还有路径压缩的时候注意更新一下kind[]就ok了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 #define MAXN 100010
 6 int parent[MAXN];
 7 int kind[MAXN];
 8 //0表示不属于同一类,1表示属于同一类
 9 int n,m;
10 
11 void Initiate()
12 {
13     for(int i=1;i<=n;i++){
14         parent[i]=i;
15     }
16     memset(kind,0,(n+2)*sizeof(kind[0]));
17 }
18 
19 int Find(int x)
20 {
21     if(x==parent[x]){
22         return parent[x];
23     }
24     int tmp=Find(parent[x]);
25     kind[x]=(kind[x]+kind[parent[x]])%2;
26     return parent[x]=tmp;
27 }
28 
29 void Union(int u,int v)
30 {
31     int r1=Find(u),r2=Find(v);
32     if(r1==r2)return ;
33     parent[r1]=r2;
34     kind[r1]=(kind[v]-kind[u]+1)%2;
35 }
36 
37 int main()
38 {
39    // freopen("1.txt","r",stdin);
40     int _case,a,b;
41     char str[4];
42     scanf("%d",&_case);
43     while(_case--){
44         scanf("%d%d",&n,&m);
45         Initiate();
46         while(m--){
47             scanf("%s%d%d",str,&a,&b);
48             if(str[0]=='D'){
49                 Union(a,b);
50             }else {
51                 int r1=Find(a),r2=Find(b);
52                 if(r1!=r2){
53                     puts("Not sure yet.");
54                 }else if(kind[a]==kind[b]){
55                     puts("In the same gang.");
56                 }else {
57                     puts("In different gangs.");
58                 }
59             }
60         }
61     }
62     return 0;
63 }
View Code

 

 

posted @ 2013-07-09 21:00  ihge2k  阅读(468)  评论(0编辑  收藏  举报