1396 家谱(并查集应用) 题解

48 篇文章 0 订阅
5 篇文章 0 订阅

题目描述

在冰岛,你的某个朋友是你的亲戚,为此有个APP就是可以测算出你和你的ta是否带有血缘关系。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。此时,如果能得到完整的家谱,判断两个人是否是亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。在这种情况下,就可以借助计算机编程来解决这个问题。为了将问题简化,你将得到一些亲戚关系的信息,比如小奇和小明是亲戚,小明和阿珂是亲戚,等等。从这些信息中,你可以推出小奇和阿珂是亲戚。请你编写一个程序,对于我们的关于亲戚关系的提问,以最快的速度给出答案。

输入

输入由两部分组成。

第一部分以N,M开始。N为问题涉及的人的个数(1≤N≤20000)。这些人的编号为1,2,3,…, N。下面有M行(1≤M≤1000000),每行有两个数ai,bi,表示已知ai和bi是亲戚。

第二部分以Q开始。以下Q行有Q个询问(1≤ Q ≤1000000),每行为ci,di,表示询问ci和di是否为亲戚。 

输出

对于每个询问ci,di,输出一行:若ci和di为亲戚,则输出“Yes”,否则输出“No”。 

一道最基础的并查集应用

first:初始化

for(int i=1;i<=n;i++){
    p[i]=i;
    cnt[i]=1;
}
//p[i]就代表i的父节点
//cnt[i]是统计每个家族人数,在本题中无用,可删去cnt数组

second:输入&加入家族

for(int i=1;i<=m;i++){
    int a,b;
    scanf("%d%d",&a,&b);
    join(a,b);
}
//下面就是join数组
void join(int x,int y){
    int x1=findth(x);
    int y1=findth(y);
    if(x1!=y1){
        p[x1]=y1;
        cnt[y1]+=cnt[x1];
    }
}

 findth函数:

int findth(int x){
    if(x==p[x])
        return x;
    else{
    	return p[x]=findth(p[x]);
	}
}

(findth是用来寻找x的祖先节点,因为x父节点不一定能是此家族祖先

third:输出部分

    int q;
    scanf("%d",&q);
    for (int i=1;i<=q;i++){
    	int a,b;
        scanf("%d%d",&a,&b);
        if (findth(p[a])==findth(p[b])){
        	printf("Yes\n");
		}else{
			printf("No\n");
		}
	}

完整(AC)代码奉上,为防止ctrl+c行为,此AC代码中有一些语法错误,需在自己理解情况上自行写出

# include <iostream>
# include <cstdion>
using namespace std;
const int maxm=1000001;
const int maxn=20001;
int p[maxn];
int cnt[maxn];
int findth(int x){
    if(x==p[x])
        return x;
    else{
    	return p[x]=findth(p[x]);
	}
}
void join(int x,int y){
    int x1=findth(x);
    int y1=findth(y);
    if(x1!=y1){
        p[x1]=y1;
        cnt[y1]+=cnt[x1];
    }
    return 0;
}
int main(){
    int n,m;
    scanf("%d%d",n,m);
    for(int i=1;i<=n;i++){
        p[i]=i;
        cnt[i]=1;
    }
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d%d",a,b);
        join(a,b);
    }
    int q;
    scanf("%d",&q);
    for (int i=1;i<=q;i++){
    	int a,b;
        scanf("%d%d",a,b);
        if (findth(p[a])==findth(p[b])){
        	printf("Yes\n");
		}else{
			printf("No\n");
		}
	}
    return 0;
}

结尾:

感谢观看

制作不易给个免费的赞吧~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值