当前位置: 首页 > news >正文

【算法】——并查集

作者:指针不指南吗
专栏:算法篇

🐾或许会很慢,但是不可以停下🐾

文章目录

  • 1.思想
  • 2.模板
  • 3.应用
    • 3.1 合并集合
    • 3.2 连通块中点的数量

1.思想

并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)
比如说,我们可以用并查集来判断 某个节点是否属于某棵树等。

  • 并查集

    1. 将两个集合合并

    2. 询问两个元素是否在一个集合当中

  • 基本原理

    每个集合用一棵树来表示。

    树根的编号就是整个集合的编号。

    每个节点存储它的父节点,p[x]表示x的父节点。

  • 相关问题

    1. 如何判断树根:if(p[x]==x)

    2. 如何求x的集合编号:while(p[x]!=x) x=p[x]

    3. 判断两个元素是否在一个集合里面,即两个元素的编号相同:find(p[x])==find(p[y])

    4. 如何合并两个集合:px是x的集合编号,py是y的集合编号。

      p[x]=y,即让一个集合 a 的根节点指向另一个集合 b 的根节点,把a直接插在b的根节点下面。

  • 优化

    • 路径压缩:让每个节点都直接指向根节点(祖先)

2.模板

并查集的类型模板这里给出三种,具体题目具体分析,看看需要维护什么,添加什么。

(1)朴素并查集:

int p[N]; //存储每个点的祖宗节点// 返回x的祖宗节点
int find(int x)
{if (p[x] != x) p[x] = find(p[x]);return p[x];
}// 初始化,假定节点编号是1~n
for (int i = 1; i <= n; i ++ ) p[i] = i;  //初始化每个元素的父节点和祖宗节点就是它本身// 合并a和 b所在的两个集合:
p[find(a)] = find(b);   //让a的祖宗节点指向b的祖宗节点,a树插在b根节点下面

(2)维护size的并查集:

int p[N], size[N];
//p[]存储每个点的祖宗节点, size[]只有祖宗节点的有意义,表示祖宗节点所在集合中的点的数量// 返回x的祖宗节点
int find(int x)
{if (p[x] != x) p[x] = find(p[x]);return p[x];
}// 初始化,假定节点编号是1~n
for (int i = 1; i <= n; i ++ )
{p[i] = i;size[i] = 1;   //初始化,每个集合里面只有一个元素
}// 合并a和b所在的两个集合:
size[find(b)] += size[find(a)];  //集合大小相加
p[find(a)] = find(b);

(3)维护到祖宗节点距离的并查集:

int p[N], d[N];
//p[]存储每个点的祖宗节点, d[x]存储x到p[x]的距离// 返回x的祖宗节点
int find(int x)
{if (p[x] != x){int u = find(p[x]);d[x] += d[p[x]];p[x] = u;}return p[x];
}// 初始化,假定节点编号是1~n
for (int i = 1; i <= n; i ++ )
{p[i] = i;d[i] = 0;
}// 合并a和b所在的两个集合:
p[find(a)] = find(b);
d[find(a)] = distance; // 根据具体问题,初始化find(a)的偏移量

3.应用

3.1 合并集合

一共有 n 个数,编号是 1∼n,最开始每个数各自在一个集合中。

现在要进行 m 个操作,操作共有两种:

  1. M a b,将编号为 a 和 b 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;
  2. Q a b,询问编号为 a 和 b 的两个数是否在同一个集合中;

输入格式

第一行输入整数 n 和 m。

接下来 m 行,每行包含一个操作指令,指令为 M a bQ a b 中的一种。

输出格式

对于每个询问指令 Q a b,都要输出一个结果,如果 a 和 b 在同一集合内,则输出 Yes,否则输出 No

每个结果占一行。

数据范围

1≤n,m≤10510^5105

输入样例:

4 5
M 1 2
M 3 4
Q 1 2
Q 1 3
Q 3 4

输出样例:

Yes
No
Yes
  • 代码实现

    #include<bits/stdc++.h>
    using namespace std;const int N=100010;int n,m; //n表示点的数量,m表示操作的次数
    int p[N];  //存的每个节点的父节点int find(int x) //返回x的祖宗节点+路径压缩
    {if(p[x]!=x)  p[x]=find(p[x]);return p[x];
    }int main()
    {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) p[i]=i; //最开始,每个点都各自在一个集合中,so父节点就是他本身;while(m--){char op[2];int a,b;scanf("%s%d %d",op,&a,&b);//合并if(op[0]=='M') p[find(a)]=p[find(b)];  //让a的祖宗节点等于b的祖宗节点,让a的祖宗节点直接插在b祖宗节点下面else{if(find(a)==find(b)) puts("Yes");  //判断是否属于同一个集合else puts("No");}  }return 0;
    }
    

注意

读入字母M或者是Q的时候,使用字符串op[2],是因为直接用char的话,可能会出现空格换行的问题作物,这种比较保险,记得在后面使用的时候,用op[0],不能直接使用op

puts自动包含换行

3.2 连通块中点的数量

给定一个包含 n 个点(编号为 1∼n)的无向图,初始时图中没有边。

现在要进行 m 个操作,操作共有三种:

  1. C a b,在点 a 和点 b 之间连一条边,a 和 b 可能相等;
  2. Q1 a b,询问点 a 和点 b 是否在同一个连通块中,a 和 b 可能相等;
  3. Q2 a,询问点 a 所在连通块中点的数量;

输入格式

第一行输入整数 n 和 m。

接下来 m 行,每行包含一个操作指令,指令为 C a bQ1 a bQ2 a 中的一种。

输出格式

对于每个询问指令 Q1 a b,如果 a 和 b 在同一个连通块中,则输出 Yes,否则输出 No

对于每个询问指令 Q2 a,输出一个整数表示点 a 所在连通块中点的数量

每个结果占一行。

数据范围

1≤n,m≤10510^5105

输入样例:

5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5

输出样例:

Yes
2
3
  • 思路

    • 连通块就是一个点的集合:集合中的点可以相互到达,直接或者是间接都是可以的;

    • 这时候我们可以把它类比成一个树,运用并查集,一个点集合,我们可以用一个编号来表示,属于同一个编号,就说明两个点之间可以相互到达,在一个连通块里面;

    • 有三个操作:

      1. 两点之间连一条边,那么这两个点所在集合中的点,都是可以相互到达的,即合成一个连通块,用并查集中的合并操作;

      2. 判断是否在一个连通块,用并查集的查询;

      3. 询问一个点集合的数量,需要我们额外维护,初始化的时候每个集合1个,合并的时候,两个集合数量相加,最后输出即可

  • 代码实现

    #include<bits/stdc++.h>using namespace std;const int N=1000010;
    int n,m;
    int p[N],sizel[N];  //p表示父节点,sizel表示集合的大小,记住sizel里面放的是祖宗节点,后面容易出错int find(int n)  //返回祖宗节点
    {if(p[n]!=n) p[n]=find(p[n]);return p[n];
    }int main()
    {scanf("%d%d",&n,&m);  //读入点的数量和操作的次数for(int i=1;i<=n;i++){   //初始化,父节点就是它本身;集合大小都是1,只有他自己p[i]=i;sizel[i]=1;}char op[5];   while(m--){scanf("%s",op);  //读入操作的名字if(op[0]=='C'){   //合并int a,b;scanf("%d%d",&a,&b);if(find(a)==find(b)) continue;  //相同则进入下个循环else{   //不同即操作,两步的顺序不能反!!!sizel[find(b)]+=sizel[find(a)];  //b的集合大小加上a的集合大小p[find(a)]=find(b);   //让a的祖宗节点指向b的祖宗节点}}else if(op[1]=='1'){  //查询是否一个集合int a,b;scanf("%d%d",&a,&b);if(find(a)==find(b))  puts("Yes");else puts("No");}else{if(op[1]=='2') {   //输出集合大小int d;scanf("%d",&d);printf("%d\n",sizel[find(d)]);  }}}return 0;
    }
    

Alt

相关文章:

【算法】——并查集

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法篇 &#x1f43e;或许会很慢&#xff0c;但是不可以停下&#x1f43e; 文章目录1.思想2.模板3.应用3.1 合并集合3.2 连通块中点的数量1.思想 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合的合并及查询问题…...

Python3,为了无损压缩gif动图,我不得不写了一个压缩神器,真香。

gif动图无损压缩1、引言2、代码实战2.1 模块介绍2.2 安装2.3 代码示例3、总结1、引言 小屌丝&#xff1a;鱼哥&#xff0c; 求助~ 求助~ 求助~ 小鱼&#xff1a;你这是告诉我&#xff0c;重要的事情 说三遍吗&#xff1f; 小屌丝&#xff1a;你可以这么理解。 小鱼&#xff1a…...

文献阅读 An implementation of the seismic resolution enhancing network based on GAN

题目 An implementation of the seismic resolution enhancing network based on GAN 基于GAN的地震分辨率增强网络的实现 摘要 对于地震数据&#xff0c;本文利用深度学习来学习不同层次的特征并将它们合并以恢复缺失的分辨率。 将GAN网络引入到地震数据处理&#xff1b;对…...

Google员工说出了我不敢说的心里话!

前言&#xff1a;本文来自Beyond的投稿&#xff0c;码农翻身做了修改。今天在Medium上看到一篇文章《The maze is in the mouse》&#xff0c;是一个刚从Google离职的员工写的&#xff0c;揭开了Google内部的各种问题&#xff0c;引发了很多人的共鸣&#xff0c;到目前为止&…...

“御黑行动”进行中,三月重保单位已开放接入!

三月重保在即&#xff0c;对于诸多政企单位来说&#xff0c;正面临着特殊时期的安全保障工作这一重要“大考”。 面对越来越专业且隐匿的攻击&#xff0c;各单位承受着巨大压力&#xff0c;尤其是政府、国企、央企等具有重要地位及广泛社会影响面的单位&#xff0c;其网站及业务…...

taobao.top.oaid.client.decrypt( 端侧OAID解密 )

&#xffe5;开放平台免费API不需用户授权 解码OAID(Open Addressee ID)&#xff0c;返回收件人信息。该接口用于客户端直接查看订单隐私数据&#xff0c;解密数据不经过ISV服务器&#xff0c;且包含风控等安全检测。 公共参数 请求地址: HTTP地址&#xff1a;http://gw.api.ta…...

QT+OpenGL鼠标操作和模型控制

文章目录QTOpenGL鼠标操作和模型控制鼠标拾取理论有点小复杂从鼠标计算射线第 0 步&#xff1a;2D 视口坐标第 1 步&#xff1a;3d归一化设备坐标第 2 步&#xff1a;4d齐次剪辑坐标第 3 步&#xff1a;4d眼(相机)坐标第 4 步&#xff1a;4d 世界坐标代码展示模型控制多模型加载…...

爱奇艺“资产重定价”:首次全年运营盈利是拐点,底层逻辑大改善

长视频行业历时一年有余的降本增效、去肥增瘦&#xff0c;迎来首个全周期圆满收官的玩家。 北京时间2月22日美股盘前&#xff0c;爱奇艺发布2022年Q4及全年财报&#xff0c;Q4 Non-GAAP净利润明显超越预期&#xff0c;且首次实现全年运营盈利。受业绩提振&#xff0c;爱奇艺盘…...

MySQL —— 库的操作

文章目录1. 创建数据库2. 字符集和校验规则3. 数据库的基本操作3.1 查看数据库3.2 显示创建数据库的语句3.3 修改数据库3.4 删除数据库3.5 备份&#xff0c;还原数据库4. 查看数据库的连接情况1. 创建数据库 基本语法&#xff1a; create database if not exists 数据库名 选项…...

修改shell的命令提示符

以下内容源于C语言中文网的学习与整理&#xff0c;非原创&#xff0c;如有侵权请告知删除。 一、命令提示符格式 从虚拟控制台登陆后&#xff0c;或者从桌面环境的终端进入shell后&#xff0c;就可以看见shell的命令提示符&#xff0c;这意味着可以输入命令了。注意&#xff…...

介绍并比较Apache Hive支持的文件格式

Apache Hive 支持几种熟知的Hadoop使用的文件格式&#xff0c;Hive也能加载并查询其他Hadoop组件创建的不同文件格式&#xff0c;如Pig或MapReduce。本文对比Hive不同文件格式&#xff0c;如&#xff1a;TextFile, SequenceFile, RCFile, AVRO, ORC,Parquet&#xff0c;Clouder…...

C语言之文件操作

目录 一、什么是文件&#xff1f; 二、C语言如何操作文件 1.操作方式 2.文件指针 2.1 定义文件指针 2.2文件的打开与关闭 2.3文件的顺序读写 2.3文件的随机读写 总结 一、什么是文件&#xff1f; 在电脑磁盘的上的文件。在程序设计中&#xff0c;分为两种&#xff1a;程序…...

Linux->父子进程初识和进程状态

目录 前言&#xff1a; 1. 父子进程创建 2. 进程状态 R(running)状态&#xff1a; S(sleep)状态&#xff1a; D(disk sleep)状态&#xff1a; T(stopped)状态&#xff1a; X(dead)和Z(zombie)状态&#xff1a; 孤儿进程&#xff1a; 前言&#xff1a; 本篇主要讲解关…...

【Linux学习笔记】5.Linux 用户和用户组管理

前言 本章介绍Linux的用户和用户组管理。 Linux 用户和用户组管理 Linux系统是一个多用户多任务的分时操作系统&#xff0c;任何一个要使用系统资源的用户&#xff0c;都必须首先向系统管理员申请一个账号&#xff0c;然后以这个账号的身份进入系统。 用户的账号一方面可以…...

茂名市 2021 年高中信息技术学科素养展评

没事干&#xff0c;发一下去年去比赛的题目。 目录 第一题 30分 第二题 30分 第一题 30分 题目&#xff1a; “姐姐&#xff0c;乘除法运算太难了&#xff0c;有什么办法能熟练掌握吗&#xff1f;”今年 读小学四年级的表弟向李红求救。为了提高表弟的运算能力&#xff0c;…...

【软件测试】测试人不躺平,进军高级自动化测试自救,你的不一样结局......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 随着测试从业年龄的…...

win10环境下安装java开发环境安装java

一&#xff1a;环境介绍 安装系统版本&#xff1a;win10 java版本&#xff1a;java SE 17 二&#xff1a;下载Java安装包 官网下载Java安装包&#xff1a;Java Downloads | Oracle 中国 选择需要的Java版本进行下载&#xff0c;如果没有要选择的版本&#xff0c;可以选择最新…...

【华为OD机试模拟题】用 C++ 实现 - 开心消消乐(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…...

opencv图像融合

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…...

没有经验的时候,怎么搞定面试?

在之前的面试技巧&#xff0c;如何写简历上面&#xff0c;我讲了一些方法&#xff0c;希望大家重 视起来。核心其实就一点&#xff1a;他们想要你表现什么能力&#xff0c;以及你在 这个能力之外还有什么。 看清楚这句话的含义&#xff0c;你就可以做到百发百中。具体怎么训练&…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

​​企业大模型服务合规指南:深度解析备案与登记制度​​

伴随AI技术的爆炸式发展&#xff0c;尤其是大模型&#xff08;LLM&#xff09;在各行各业的深度应用和整合&#xff0c;企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者&#xff0c;还是积极拥抱AI转型的传统企业&#xff0c;在面向公众…...