普通并查集

并查集

c++中的并查集:什么是并查集 并查集有什么用处呢? 如何灵活使用普通的并查集操作呢?

普通并查集 概论:

定义:
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。

一般的并查集主要记录节点之间的链接关系,而没有其他的具体的信息,仅仅代表某个节点与其父节点之间存在联系,它多用来判断图的连通性

在这里插入图片描述

图片选自csdn博客

总体来说,他是一种树状数据联系的查询与分配方法。

比如说,我们可以用并查集来判断一个森林中有几棵树、某个节点是否属于某棵树等。

主要构成:
并查集主要由一个整型数组pre[ ]和两个函数find( )、join( )构成。
数组 pre[ ] 记录了每个点的前驱节点是谁,函数 find(x) 用于查找指定节点 x 属于哪个集合,函数 join(x,y) 用于合并两个节点 x 和 y 。

普通并查集的作用:

并查集的主要作用是求连通分支数(如果一个图中所有点都存在可达关系(直接或间接相连),则此图的连通分支数为1;如果此图有两大子图各自全部可达,则此图的连通分支数为2……)

调度分配每一个人对于某一群人的所属关系,帮派的划分,父与子的关系图等等。

就像刚才说的,它用于联系每个数据使之成为一个树状数据。

数据结构的角度来看:
由于我们的重点是在关注两个人是否连通,因此他们具体是如何连通的,内部结构是怎样的,甚至根节点是哪个都不重要。

普通并查集的使用 代码编写:

首先我们要定义一个一维数组 f [maxn](maxn是一个数字,它可以根据题目要求而设定,但是我一般把他设置的很大,避免数据超过数组范围导致段错误,但同时他会消耗分配内存)

这个数组他记录了每个人他本身的数据和他的父级数据,例如f[16] = 6 意思是16号的上级是6号。

如果一个数据的下标是数据本身(例如:f[10] = 10) 那么这个数据就是本树状数据的牢大(最高级的那一位)。

但是这个查询的顺序想必大家也能看出来一点——他是一级一级向上去寻找的,所以过会要讲到的并查集find函数就是这样一个原理。

//local:
int n;
int f[100010];

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

//后面的main中只需要输入n和调用init()就行.

上述是一个普通并查集的数组初始化,一目了然对吧.

int find(int a)
{
    return a ? f[a] == find(a) : a;
}

上述是一个查找首级的并查集寻找函数find(int _a),他的最大作用就是不停的向上摸索上级,直到他找到首级结束,用一个异或运算让他的代码字节量压缩到清晰易懂轻量的形式.

void merge(int a,int b)
{
    int fa = find(a);
    int fb = find(b);
    if(fa != fb) f[fa] = fb;
}

上述是一个普通并查集的合并操作merge(int _a,int _b) 其作用基于find函数上寻找某个节点的首级,然后将一个首级 替换为另一个首级 (也就相当于将这个树状数据尾插到另一个树状数据低下)

板子like this:

P3367 【模板】并查集 - 洛谷 | 计算机科学教育新生态

#include <iostream>

using namespace std;
int n,m;
int z,x,y;
int f[100010];
void init()
{
    for(int i = 1;i<=n;i++) f[i] = i;
}

int find(int a)
{
    return (f[a]==a) ? a : f[a] = find(f[a]);
}

void merge(int a,int b)
{
    int fa = find(a);
    int fb = find(b);
    if(fa!=fb) f[fa] = fb;
}

bool judge(int a , int b)
{
    return find(a)==find(b);
}

int main(void)
{
    cin>>n>>m;
    init();
    for(int i =0;i<m;i++)
    {
        cin >> z >> x >> y;
        if(z==1)
        {
            merge(x,y);
        }
        else
        {
            if(judge(x,y)) cout << "Y" << endl;
            else cout << "N" << endl;
        }
    }
    return 0;
}
//请勿抄袭,锁号不负责!

下一次讲 什么是 加权并查集.

written by nil_the_Hedgehog 紫色刺猬🦔 (Tonyl1n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值