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

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值