最重要的数据结构——并查集

我们今天来讲一个大部分竞赛生都最喜欢的一个数据结构——并查集

我们先从一道题入手:亲戚

这时并查集最经典的例题(注意!没有之一!)

我们来看一下这道题,大佬们肯定第一思路就是传递闭包(但是我认为没有没学过并查集的大佬)

我们仔细看看,人数小于等于5000呢!(刚好5000的话Floyd传递闭包大约需要21分钟才能跑出来(ˉ▽ˉ;)...)

这时,我们不得不用并查集了!

先定义一个father数组(用来存某个节点的祖宗)

#include<bits/stdc++.h>
#define MAX 5010
using namespace std;
int father[MAX];
int main(){

    return 0;
}

其实两个人是否是亲戚,其实就是判断他们的祖先是否是一个人,

那么我们必须写一个判断是否是祖先的代码,如果我们用while循环的话其实不是很好操作(实际上我也没有试过)

大佬们肯定第一个想到的就是递归,我们怎们结束这个递归呢?这是一个十分让新手头痛的问题。

其实十分简单,如果它自己的父亲都是自己的话,那么他肯定是这棵树的祖宗了,其实他是自己的父亲就表示他是这棵树的祖宗了qwq

如果上面的假设条件不成立的话,我们只需要继续找它父亲的父亲是谁这一直递归就行了

所以呢我们就可以写出找x的祖宗的代码:

int find(int x){
    if(father[x] == x) return x;
    return find(father[x]);
}

当然,如果你是大佬,看到上面的代码肯定非常不爽(*  ̄︿ ̄),心里想:不都是一排代码搞定吗?这个🐖作者真是的!(那么你喜欢的代码来了!)

int find(int x){ return father[x] == x ? x : find(father[x]);} 

我们接下来看并查集的初始化:(这个用不着讲)

for(int i = 1 ; i <= n ; i++) father[i] = i;

其他的就很简单了,接下来看我的AC代码!

#include<bits/stdc++.h>
#define MAX 5010
using namespace std;
int father[MAX], x, y, n, m, p;
int find(int x){return father[x] == x ? x : find(father[x]);}
int main(){
    scanf("%d%d%d", &n, &m, &p);
    for(int i = 1 ; i <= n ; i++) father[i] = i;
    for(int i = 1 ; i <= m ; i++){
        scanf("%d%d", &x, &y);
        father[x] = find(x);
        father[y] = find(y);
        if(father[x] != father[y]) father[father[x]] = father[father[y]];
    }
    for(int i = 1 ; i <= p ; i++){
        scanf("%d%d", &x, &y);
        if(find(x) == find(y)) cout<<"Yes\n";
        else cout<<"No\n";
    }
    return 0;
}

今天的并查集就讲到这里了,希望你们有所收获!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值