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

 

 

你可能感兴趣的:(并查集)