并查集知识梳理

并查集


这一章中用到里树的基础知识,不懂的朋友看这里

并查集的定义

  1. 并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。
  2. 并查集通常包含两种操作:
    查找(Find):查询两个元素是否在同一个集合中
    合并(Union):把两个不相交的集合合并为一个集合
  3. 组词解释法:并:合并,查:查找,集:集合。连成一句话来说就是用来合并、查找的集合

并查集的思想

开始所有点上级都为它本身

下标 0 1 2 3 4 5
上级 0 1 2 3 4 5

把2,3合并到0(树1),

把4,5合并到1(树2)

下标 0 1 2 3 4 5
上级 0 1 0 0 1 1

把1合并到0(合并树1,树2)

下标 0 1 2 3 4 5
上级 0 0 0 0 1 1

朴素并查集的代码

(1)初始化

int parent[105];//记录自己的上级
void init(int n) {
    for(int i = 0;i < n;i ++) {
        parent[i] = i;//将自己的上级赋值为自己
    }
}

现在所有点上级都为它本身

下标 0 1 2 3 4 5
上级 0 1 2 3 4 5

(2)查找

int find(int x) {
    if(parent[x] == x) {//判断自己是不是自己的上级
        return x;
    } else {
        return find(parent[x]);//如果不是,查找自己上级的上级
    }
}

查找时要一层一层的访问自己的上级,自己到自己是自己的上级为止

下标 0 1 2 3 4 5
上级 0 0 0 0 1 1

举例:访问4的上级

路径:4->1,1->0

(3)合并

//把j合并到i中去
void merge(int i,int j) {
    parent[find(j)]=find(i);//把j的上级设为i的上级
}

下标 0 1 2 3 4 5
上级 0 1 0 0 1 1

下标 0 1 2 3 4 5
上级 0 0 0 0 1 1

将1合并到0
学到这里我们来看一看擒贼先擒王(记得先动手自己做)

路径压缩

作用:

提高并查集效率

举一个极端的例子:

假设我们一共有1e9个点,如图一直排列下去

那么我们查找就需要o(n)的复杂度(就会爆炸)

但办法是人想出来的,记住并查集是一个树形结构,然后就有了下图的优化

这样一来时间复杂度就只有o(logn)了(十分的诱人呢)

接下来是上代码时间

(1)查找代码

版本一:

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

版本二:

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

(2)路径压缩完整代码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100;
int parent[MAXN];
void init (int n) {//初始化
    for (int i = 1;i <= n;i ++){
        parent[i] = i;
    }
}
int find (int x) {//查找
    if (parent[x] == x) {
       return x; 
    } else {
        parent[x] = find(parent[x]);
        return parent[x];
    }
}
void merge (int i,int j) {//合并
    parent[j] = find(i);
}
int main() {
    return 0;
}

按秩合并

思想

如果现在要合并两一棵树,那么我们应该怎么去合并最优呢?

是从右边到左边?还是从左边到右边?谁是合并后的根节点?

显然这种情况下,我们有两种合并方法:

方法一:

方法二:

我们通过路径压缩知道,深度越浅时间复杂度的上限越小

所以,明显方法二才是最优解

实现

(1)初始化

void init(int n) {
    for(int i = 0;i < n;i ++) {
        parent[i] = i;
        rank[i] = 1;//rank用来记录深度,开始一为一棵树,所以赋值为1
    }
}

(2)合并

void merge (int i,int j) {//合并
    int x = find(i),y = find(j);
    if(rank[x] < rank[y]) {//x作为根节点和y作为根节点的子树的深度比较
        parent[x] = y;//小于则把x合并到y
    } else {
        parent[y] = x;//大于则把y合并到x
    }
    if(rank[x] == rank[y] && x != y) {
        rank[x] ++;//如果两棵树深度相同,那么rank[x] + 1;
    }
}

习题

「NOI2015」程序自动分析
「JSOI2008」星球大战
「NOI2001」食物链
「NOI2002」银河英雄传说

完结撒花

欢迎大家留言
小编蒟蒻一个,有什么问题请大佬不惜赐教Orz

posted @   骆美辰  阅读(149)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
  1. 1 淋雨一直走 张韶涵
  2. 2 一期一会《未闻花名》(Cover 茅野愛衣,戸松遥,早見沙織) 周深
  3. 3 起风了 吴青峰
  4. 4 极恶都市 夏日入侵企划
淋雨一直走 - 张韶涵
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 姚若龙

作曲 : Henrik Tala/Hermanni Kovalainen/Ilanguaq Lumholt

编曲 : DJ Mobster Productions

制作人 : Jae Chong

Oh~ 人都应该有梦

有梦就别怕痛

有雷声在轰不停

雨泼进眼里看不清

谁急速狂飙

溅我一身 的泥泞

很确定我想去哪里

往天堂要跳过地狱

也不恐惧

不逃避

这不是脾气

这不是脾气

是所谓志气 与勇气

你能推我下悬崖

我能学会飞行

从不听

谁的命令

很独立

耳朵用来听自己的心灵

淋雨一直走

淋雨一直走

是一颗宝石就该闪烁

人都应该有梦

Oh

有梦就别怕痛

淋雨一直走

是道阳光就该暖和

人都应该有梦

Oh

有梦就别怕痛

有前面盘旋的秃鹰

有前面盘旋的秃鹰

有背后尖酸的耳语

黑色的童话

是给长大的洗礼

要独特才是流行

无法复制的自己

让我连受伤也有型

这不是脾气

是所谓志气 与勇气

你能推我下悬崖

我能学会飞行

从不听

谁的命令

很独立

耳朵用来听自己的心灵

淋雨一直走

淋雨一直走

是一颗宝石就该闪烁

人都应该有梦

Oh

有梦就别怕痛

淋雨一直走

是道阳光就该暖和

人都应该有梦

Oh

有梦就别怕痛

有时掉进黑洞

有时掉进黑洞

有时掉进黑洞

有时候爬上彩虹

在下一秒钟

命运如何转动

没有人会晓得 Oh

我说希望无穷

你猜美梦成空

相信和怀疑

总要决斗

淋雨一直走

淋雨一直走

是一颗宝石就该闪烁

人都应该有梦

Oh

有梦就别怕痛

淋雨一直走

是道阳光就该暖和

人都应该有梦

Oh

有梦就别怕痛

淋雨一直走

淋雨一直走

是一颗宝石就该闪烁

人都应该有梦

Oh

有梦就别怕痛

淋雨一直走

是道阳光就该暖和

人都应该有梦

Oh

有梦就别怕痛

OC/OA : Hermanni Kovalainen/Ilanguaq Lumholt/Henrik Tala

配唱制作人 : Jae Chong

配唱制作人 : Jae Chong

计算机程序编写 : DJ Mobster

录音师 : 潘尧泓

录音室 : Lights Up Studio (台北)

混音师 : Jae Chong

混音室 : AZIATIX Studio

OP : Warner/Chappell Music Finland / DJ Mobster Publishing

SP : Warner/Chappell Music Taiwan Ltd.

ISRC TW-R03-12-02003

lock: { enable: true, background: 'https://img1.baidu.com/it/u=2788089125,168843488&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1690563600&t=35fa4326e773b3fbf83562ad746b7cd2',//锁屏背景 strings: [ 'Every win named never give up 每一份胜利都叫不放弃',//签名 ], },
点击右上角即可分享
微信分享提示