算法笔记p328_并查集

目录

  • 并查集的定义
  • 并查集的基本操作
    • 初始化
    • 查找
    • 合并
  • 路径压缩

并查集的定义

并查集是一种维护集合的数据结构,支持下面两个操作:

  1. 合并:合并两个集合。
  2. 查找:判断两个元素是否在一个集合。

并查集用一个数组实现:

int father[N];
  1. father[i]表示元素i的父亲结点,而父亲结点本身也是这个集合内的元素(1 ≤ i ≤ N)。
  2. 如果father[i] == i,则说明元素i是该集合的根结点。
  3. 对同一个集合来说只存在一个根结点,且将其作为所属集合的标识

并查集的基本操作

初始化

一开始,每个元素都是独立的一个集合,因此需要令所有father[i]等于i():

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

查找

对给定结点寻找其根结点(即father[i] == i的结点)的过程。

  1. 递推代码
// findFather函数返回元素x所在集合的根结点
int findFather(int x) {while (x != father[x])  // 如果不是根结点,继续循环x = father[x];      // 获得自己的父亲结点return x;
}
  1. 递归代码
int findFather(int x) {if (x == father[x])return x;elsereturn findFather(father[x]);
}

合并

  1. 对于给定的两个元素a、b,判断它们是否属于同一集合。可以调用上面的查找函数,对这两个元素a、b分别查找根结点,然后再判断其根结点是否相同。
  2. 合并两个集合:在①中已经获得了两个元素的根结点faA和faB,因此只需要把其中一个的父亲结点指向另一个结点即可。如令father[faA] = faB。
  3. 在合并过程中,只对两个不同集合进行合并,如果两个元素在相同的集合中,则不进行合并操作。这样保证了在同一个集合中一定不会产生环,即并查集产生的每个集合都是一棵树
void Union(int a, int b) {int faA = findFather(a);    // 查找a的根结点,记为faAint faB = findFather(b);    // 查找b的根结点,记为faBif (faA != faB)             // 如果不属于同一个集合father[faA] = faB;      // 合并它们
}

路径压缩

把当前查询结点的路径上的所有结点的父亲都指向根结点,查找的时候就不需要一直回溯去找父亲了,查询的复杂度可以降为O(1)。

  1. 按原先的写法获得x的根结点r。
  2. 重新从x开始走一遍寻找根结点的过程,把路径上经过的所有结点的父亲全部改为根结点r。

递推版本:

int findFather(int x) {int a = x;              // 保存原先的xwhile (x != father[x])  // 寻找x的根结点x = father[x];      // 循环结束后,x存放的是根节点// 下面把路径上的所有结点的father都改为根结点while (a != father[a]) {int z = a;          // 保存原先的aa = father[a];      // a回溯父亲结点father[z] = x;      // 将原先的结点a的父亲改为根结点x}return x;               // 返回根结点
}

递归版本:

int findFather(int x) {if (x == father[x])                 // 找到根结点return x;else {int r = findFather(father[x]);  // 递归寻找father[x]的根结点rfather[x] = r;                  // 将根结点r赋值给father[x]return r;                       // 返回根结点r}
}

或者

int findFather(int x) {if (x != father[x])                     // x不是根结点father[x] = findFather(father[x]);  // 找到x父亲结点根结点,并做路径压缩return father[x];                       // 返回根结点
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/753734.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenJudge - 12:计算2的N次方

总时间限制: 1000ms 内存限制: 65536kB 描述 任意给定一个正整数N(N<100)&#xff0c;计算2的n次方的值。 输入 输入一个正整数N。 输出 输出2的N次方的值。 样例输入 5 样例输出 32 关键代码 #include<stdio.h> int main() {int n,a[51] {0},c[51] {0},count 0…

Day68:WEB攻防-Java安全原生反序列化SpringBoot攻防heapdump提取CVE

目录 Java安全-反序列化-原生序列化类函数 原生序列化类函数 SnakeYaml XMLDecoder ObjectInputStream.readObject 工具利用 ysoserial Yakit SerializedPayloadGenerator Java安全-SpringBoot框架-泄漏&CVE SpringBoot Actuator-黑白盒发现 人工识别 BurpSui…

数据库事务中“锁”的分类

数据库事务中的锁可以按照不同的维度进行分类。以下是一些常见的分类方式&#xff1a; 1、按锁的粒度分类&#xff1a; 行锁&#xff08;Row-level lock&#xff09;&#xff1a;锁定单个或少量的数据行。这种锁粒度小&#xff0c;允许高度的并发&#xff0c;但管理开销大。页…

LeetCode 2312.卖木头块:动态规划(DP)

【LetMeFly】2312.卖木头块&#xff1a;动态规划(DP) 力扣题目链接&#xff1a;https://leetcode.cn/problems/selling-pieces-of-wood/ 给你两个整数 m 和 n &#xff0c;分别表示一块矩形木块的高和宽。同时给你一个二维整数数组 prices &#xff0c;其中 prices[i] [hi, …

【蓝桥杯】蓝桥杯嵌入式——题目总结及文章汇总(内含客观题与主观题,并且都附有详细题解)

介绍 蓝桥杯嵌入式比赛是一项专注于嵌入式开发的全国性比赛&#xff0c;旨在鼓励和促进嵌入式系统的研究和应用&#xff0c;提高嵌入式开发的水平和技能。 比赛分为初赛和复赛两个阶段。初赛难度适中&#xff0c;注重考查参赛选手的嵌入式系统开发能力和实践经验。复赛则采用线…

LeetCode118 杨辉三角形

题目 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRows 1 输出: [[1]] 解…

汽车电子拓扑架构的演进过程

汽车电子拓扑架构的演进过程 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师 (Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再挣扎,出门靠…

TestNg @Test的expectedExceptionsMessageRegExp属性

本文将讨论TestNG中Test 注解的expectedExceptionsMessageRegExp属性。 这个属性有什么作用&#xff1f;根据文档&#xff1a; 如果指定了expectedExceptions &#xff0c;则其消息必须与此属性中指定的正则表达式匹配。 因此&#xff0c;这意味着如果不先使用expectedparam…

爬虫加密算法

js常见的加密方式 加密在前端开发和爬虫中是经常遇见的。掌握了加密算法且可以将加密的密文进行解密破解的&#xff0c;也是你从一个编程小白到大神级别质的一个飞跃。且加密算法的熟练和剖析也是很有助于帮助我们实现高效的js逆向。下述只把我们常用的加密方法进行总结。不去深…

若依ruoyi-vue中的的DTO、VO、BO、PO、DO、POJO

POJO POJO的定义是无规则简单的对象&#xff0c;在日常的代码分层中pojo会被分为VO、BO、 PO、 DTO VO &#xff08;view object/value object&#xff09;表示层对象 1、前端展示的数据&#xff0c;在接口数据返回给前端的时候需要转成VO 2、个人理解使用场景&#xff0c;接…

Python 常用的开源爬虫库介绍

Python 是一种广泛使用的编程语言&#xff0c;特别是在 Web 爬虫领域。有许多优秀的开源爬虫库可以帮助开发者高效地抓取网页内容。以下是几个常用的 Python 爬虫库及其特点和优势&#xff1a; BeautifulSoup 特点 - **HTML/XML 解析**&#xff1a;BeautifulSoup 是一个…

linux(Ubuntu22) 一篇带你学会Linux,详细篇

Linux 简介 精通Linux&#xff0c;自带python&#xff0c;系统开源 电脑可安装双系统 c盘安装win D盘安装linux 在一套硬件上只能同时运行一个操作系统 虚拟机 模拟真实环境 在虚拟机内运行操作系统 需要硬件支持虚拟化 开启VT-X VM…

opengl程序错误,无法定位程序输入点 glewGetErrorString@4 于动态链接库

使用mingw编译器编译运行opengl程序&#xff0c;编译通过运行时崩溃 怀疑是之前的mingw版本编译的glew库版本不对&#xff0c;又重新编译一遍&#xff0c;还是这个错误 之后检查环境变量配置&#xff0c;发现有两个glew的路径&#xff0c;一个是msvc版的&#xff0c;另一个是m…

JavaScript 语法-对象

对象 JavaScript 中的对象是一组键值对的集合&#xff0c;其中每个键都是字符串&#xff0c;每个值可以是任意类型。 对象是由一些属性和方法组成的集合&#xff0c;属性可以用来存储数据&#xff0c;方法可以用来操作数据。 属性和方法使用“.”来访问 // 创建一个对象 let …

教你把公司吃干抹净、榨干带走

大家好&#xff1a; 衷心希望各位点赞。 您的问题请留在评论区&#xff0c;我会及时回答 正文 打工人一定要做到够自私&#xff0c;把公司的一切为我所用&#xff0c;你要知道闷头打工是没有出路的。聪明的人会以最快的速度榨干带走公司的一切资源、人脉、技能&#xff0c;为…

五种主流数据库:数据汇总

汇总分析是数据报表中的基本功能&#xff0c;例如产品销售金额的汇总、学生的平均身高和标准差统计等。SQL 定义了聚合函数&#xff0c;可以实现数据的汇总分析。 本文比较五种主流数据库支持的常见聚合函数&#xff0c;包括 MySQL、Oracle、SQL Server、PostgreSQL 以及 SQLi…

【C++PCL】点云处理RANSAC配准

目录 1.原理介绍 2.代码效果 3.源码展示 4.参数调试 5.注意事项

Unity WebGL服务器标头的问题

目录 现象&#xff1a; 报错文本: 原因: 解决方案: 现象&#xff1a; 打包前&#xff0c;ProjectSetting 压缩选项设置为Brotli, 将打包的WebGL部署到阿里云OSS环境后&#xff0c;运行弹框提示错误. 报错文本: Unable to parse Build/WebGL.framework.js.br! This canha…

二、Jooq整合SpringBoot

在当前微服务盛行的情况下&#xff0c;Spring Boot 或 Spring Cloud 为基础的微服务体系是主流&#xff0c; 也是目前业务场景中新的选型方向 数据库表 -- filesystem.user definitionCREATE TABLE user (id int(11) NOT NULL AUTO_INCREMENT,username varchar(50) NOT NULL,…

三级等保技术建议书

1信息系统详细设计方案 1.1安全建设需求分析 1.1.1网络结构安全 1.1.2边界安全风险与需求分析 1.1.3运维风险需求分析 1.1.4关键服务器管理风险分析 1.1.5关键服务器用户操作管理风险分析 1.1.6数据库敏感数据运维风险分析 1.1.7“人机”运维操作行为风险综合分析 1.2…