并查集+例题

本文详细介绍了并查集这种数据结构,包括其基本组成部分、压缩路径操作和实现方式。并通过四个具体例题,展示了如何运用并查集解决实际问题,涉及不同场景的并查集应用策略和代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

并查集的功能:

1:非常快的检查两个元素是否属于一个集合。

2:两个元素各自所在的集合,请你把它合并在一起。

并查集的基本组成部分(所用到的数据结构):

并查集有三个函数(也可以是两个)

一:find函数:寻找某个节点所在集合的头节点。

二:union函数:合并两个节点所在的集合。

三:issameset函数:判断两个节点是否属于一个集合。

所用到的数据结构:

数组:定义一个pre数组,pre[i]代表i节点的父节点,定义一个size数组,size[i]代表i节点所在的集合的元素的个数

map:定义一个fathermap,fathermap的key代表节点,value代表key节点的父节点,定义一个sizemap,sizemap的key也代表节点,sizemap的value代表key节点所在集合的节点个数

并查集压缩路径操作:

压缩路径:直接看图:

这就是路径压缩。

为什么要进行路径压缩呢?

当我们要查询4号节点和5号节点是否在一个集合中时,如果不进行路径压缩,那么就是上面的左图,从4号顶点一直走到1号顶点,从5号顶点一直走到1号顶点,很浪费时间。如果进行了路径压缩,那么就是上面的右图,从4号顶点走到1号顶点很方便,从5号顶点走到1号顶点也很方便。这就是并查集为什么能够很快的检查出两个元素是否属于一个集合的原因之一。

并查集的实现:

代码如下:

#include<bits/stdc++.h>
#define MAXN 9999
using namespace std;
int a[MAXN];//用户提供的数据,必须一次性全部提供完
int n;//用户提供数据的个数
class unionfindset
{
private:
    map < int,int >fathermap;//fathermap代表i节点(前面的int)的父亲节点(后面的int)
    map < int,int >sizemap;//sizemap代表i节点(前面的int)所属的集合的大小(后面的int)
    int findhead(int head)//寻找head节点所在集合的头节点,并压缩路径
    {                              
        int z=fathermap.find(head);//head节点的父亲节点(不一定是所在集合的头节点)
        if(z==head)//找到了该集合的头节点
            return head;
        int father=findhead(z);//这个father变量始终是集合的头节点,不能变
        fathermap[head]=father;//压缩路径
        return father;//返回这个father,这样保证了father不会改变
    }
public:
    unionfindset()//构造函数,对两个map赋初值
    {
        for(int i=1;i<=n;i++)
        {
            fathermap[a[i]]=a[i];//我们设定刚开始有n个集合,每个集合的头节点都是自己本身
            sizemap[a[i]]=1;//大小为1
        }
    }
    bool issameset(int a,int b)//判断节点a和节点b是否属于同一个集合
    {
        return findhead(a)==findhead(b);
    }
    void uniona(int a,int b)//合并节点a和节点b
    {
        int heada=findhead(a);//找到a所在集合的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值