poj 1703 Find them, Catch them(裸地种类并查集)

昂,poj终于在三天前修复了,这题也终于交掉了,这题自己思考种类并查集的,出了不少的错误,也正因为这些错误让我对种类并查集的理解更加的深刻~继续努力吧
题目链接:http://poj.org/problem?id=1703
题目大意:警察抓了两个帮派(龙帮和蛇帮)的人,然后给你条件说明(D)这两个编号的罪犯不是一个帮派的人,又给你一个条件(A)让你判断这两个编号的罪犯是不是一个帮派。
输入数据:
第一行:测试数据有多少组
第二行: N(罪犯的个数) M(有多少组关系和判断)
接下来的M行
A : 判断x和y在不在一个帮派,不知道关系输出Not sure yet. 不在一个帮派In different gangs. 在同一个In the same gang.
D:x和y不在同一个帮派
解题思路:
不用多想种类并查集一定是可以ac的~这题让我对种类并查集的unite和find有了更深刻的理解

初始化函数(深刻理解):
我总是喜欢用0,1,2……来区别集团是否相同是否不同,但是是以0为一个集团,1为一个集团的,现在彻底修正了,gp[i]=0是i和pa[i]是一个集团,gp[i]=1表示i和pa[i]不是一个集团的
find函数

int find(int n){
    if(n!=pa[n]){
        int tmp=pa[n];//先存一下原先的父节点
        pa[n]=find(pa[n]);//先压缩,这样可以更好的维护树型结构
        gp[n]=(gp[n]+gp[tmp])%2;//压缩后赋值
    } 
    return pa[n];
}

对与find函数的理解,还是不会的可以自己画图模拟

uinte函数:

void unite(int x,int y){
    int fx=find(x);
    int fy=find(y);
    pa[fy]=fx; //树可以直接把两个根节点连在一起
    gp[fy]=(gp[x]+gp[y]+1)%2;
}

当计算gp[fy]的时候,这个时候两棵树的深度都是2,所以就可以分情况列出来:
1、gp[x/y]=0 的时候,根节点fy和fx不是一个帮派,为1.
2、都为1的时候,fy和fx不是一个帮派,为1,。
3,gp[x/y]其中有一个是0的情况,fy和fx是一个帮派,为0。
就可以得到gp[fy]=(gp[x]+gp[y]+1)%2;

#include<cstdio>
#include<cstring>
using namespace std;
const int max=100000+50;
int pa[max],gp[max];

void init(int n){
   for(int i=1;i<=n;i++){
    pa[i]=i;gp[i]=0;
   }
}

int find(int n){
    if(n!=pa[n]){
        int tmp=pa[n];
        pa[n]=find(pa[n]);
        gp[n]=(gp[n]+gp[tmp])%2;
    } 
    return pa[n];
}

void unite(int x,int y){
    int fx=find(x);
    int fy=find(y);
    pa[fy]=fx;
    gp[fy]=(gp[x]+gp[y]+1)%2; 
}

int main(){
    int n,a,b;
    char m;
    scanf("%d",&n);
    while(n--){
        scanf("%d%d",&a,&b);getchar();
        init(a);
        int x,y;
        for(int j=0;j<b;j++){
            scanf("%c%d%d",&m,&x,&y); getchar(); 
            if(m=='A'&&a==2){
                printf("In different gangs.\n");
                continue;
            }
            if(m=='D')
                unite(x,y);
            else if(m=='A'){
                if(find(x) == find(y)){
                    if((gp[x]+gp[y])%2) printf("In different gangs.\n");//这个是奇偶树判断,也可以用&1位运算判断xy对根节点的关系
                    else printf("In the same gang.\n");
                }
                /* if(find(x)==find(y)){
                                   if(gp[x]==gp[y]) printf("In the same gang.\n");
                                   else printf("In different gangs.\n");  
                                }*/用这个方法判断也是可以的
                else printf("Not sure yet.\n");
            }   
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值