洛谷 P1551 亲戚

【题目链接】

洛谷 P1551 亲戚

【题目考点】

1. 并查集

【解题思路】

每组互相是亲戚的人构成一个集合,如果两人是亲戚,那么调用merge函数让两人所在的集合合并,。
并查集中,每个集合由一个树来表示,树的根结点代表一个集合。find函数可以返回一个结点所在集合的根结点。
对于多组询问,判断两人是否在一个集合中,即为判断两人所在集合的根结点是否相同。

【题解代码】

解法1:并查集
  • 写法1:递归查询+路径压缩,简单合并
#include<bits/stdc++.h>
using namespace std;
#define N 5005
int fa[N];
void initFa(int n)
{
	for(int i = 1; i <= n; ++i)
		fa[i] = i;
}
int find(int x)
{
	if(x == fa[x])
		return x;
	else
		return fa[x] = find(fa[x]);
}
void merge(int x, int y)
{
	fa[find(x)] = find(y);
}
int main()
{
	int n, m, p, a, b;
	cin >> n >> m >> p;
	initFa(n);
	for(int i = 1; i <= m; ++i)
	{
		cin >> a >> b;
		merge(a, b);
	}
	while(p--)
	{
		cin >> a >> b;
		cout << (find(a) == find(b) ? "Yes" : "No") << endl;
	}
	return 0;
}
  • 写法2:非递归查询,按秩合并
#include<bits/stdc++.h>
using namespace std;
#define N 5005
int fa[N], rk[N];//fa[i]:结点i的双亲结点 rk[i]:以结点i为根结点的树的秩 
void initFa(int n)
{
	for(int i = 1; i <= n; ++i)
		fa[i] = i;
}
int find(int x)//非递归查询与路径压缩 
{
    int k, t, r;//r:根结点  
    k = r = x;
    while(r != fa[r])     //查找根结点
        r = fa[r];      //找到根结点,用r记录        
    while(k != r)//路径压缩:将从x到r的整条路径上的结点的父结点都设为r
    {
        t = fa[k];       //用t暂存k的父结点
        fa[k] = r;       //fa[k]指向根结点
        k = t;           //k指向暂存的父结点 
    }
    return r;         //返回根结点            
}
void merge(int i, int j)//按秩合并i结点和j结点所在的集合
{
    int x = find(i), y = find(j);//先找到两个根结点
    if(x == y) return;//根结点相同,就不用合并了 
    if(rk[x] < rk[y])//高度低的树作为高度高的树的子树
        fa[x] = y;
    else if(rk[x] > rk[y])
        fa[y] = x;
    else//如果高度相同,则新的树的高度+1
    {
        fa[x] = y;
        rk[y]++;
    }
}
int main()
{
	int n, m, p, a, b;
	cin >> n >> m >> p;
	initFa(n);
	for(int i = 1; i <= m; ++i)
	{
		cin >> a >> b;
		merge(a, b);
	}
	while(p--)
	{
		cin >> a >> b;
		cout << (find(a) == find(b) ? "Yes" : "No") << endl;
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值