算法学习 —— 并查集

news/发布时间2024/5/15 14:00:22

(洛谷P1551)亲戚

题目背景
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
题目描述
规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。
输入格式
第一行:三个整数n,m,p,(n<=5000,m<=5000,p<=5000),分别表示有n个人,m个亲戚关系,询问p对亲戚关系。
以下m行:每行两个数Mi,Mj,1<=Mi,Mj<=N,表示Mi和Mj具有亲戚关系。
接下来p行:每行两个数Pi,Pj,询问Pi和Pj是否具有亲戚关系。
输出格式
P行,每行一个’Yes’或’No’。表示第i个询问的答案为“具有”或“不具有”亲戚关系。

要解决这样一种多个亲戚的关系,我们可以采用并查集的方法。那么什么是并查集呢?定义如下:

并查集是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素。

顾名思义,并查集支持两种操作:

合并(Union):合并两个元素所属集合(合并对应的树)
查询(Find):查询某个元素所属集合(查询对应的树的根节点),这可以用于判断两个元素是否属于同一集合

只看概念很难理解这到底是什么东西。我们将用通俗易懂的语言来解释什么是并查集。
首先在一个集合中将有关的元素连接起来形成树的结构,再遇到相关元素时,将新元素插入到树中,这样在查询A与B的相关性时我们可以通过对A祖宗节点的查询判断相关性(都连接在一起了)。
原本是
在这里插入图片描述
现在是
在这里插入图片描述
由此我们可以写出并查集的代码。
初始化

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

其中fa数组用来存储对应角标元素的爹
初始化时自己是自己的爹

查询
查询时我们需要在一次没找到对应关系后进行递归查询,万一是哪位祖宗呢?

int find(int x)
{if(fa[x] == x)return x;elsereturn find(fa[x]);
}

合并
将两个树的根节点一个附着在另一个上当儿子就行

inline void merge(int i, int j)
{fa[find(i)] = find(j);
}

路径压缩

随着加入的节点越来越多,我们会发现,这个树会变成这样:
在这里插入图片描述
很明显,这样是很不便与我们找寻根节点的。
因此,我们需要将这棵树变成这样:
在这里插入图片描述
将节点直接与根节点相连接,就能在查找时变得更快。

我们该怎么实现呢?
很简单,我们只需在查找父节点时顺手将该元素目前的父节点更改为递归的值,就行了。

int find(int x)
{if(x == fa[x])return x;else{fa[x] = find(fa[x]);  //父节点设为根节点return fa[x];         //返回父节点}
}

是不是很简单?使用三问表达式我们还能更简单:

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

这样我们就可以得到结果了。

按秩合并

当我们遇到两颗树时,我们该把哪一颗树保留,让另一颗树往上补呢?
在这里插入图片描述
如这种情况下,是8做7的儿子还是7作8的儿子呢?当然是将8向7上靠。因为这样我们得出的树的最终深度将会最小,我们查询所耗费的时间将会是最小。同理,我们在合并两颗树的时候,应当按照深度来决定谁作父节点。这就是按秩合并的含义。

在代码实现中,我们引入一个新的数组rank来记录树的深度。
初始化

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

合并

inline void merge(int i, int j)
{int x = find(i), y = find(j);    //先找到两个根节点if (rank[x] <= rank[y])fa[x] = y;elsefa[y] = x;if (rank[x] == rank[y] && x != y)rank[y]++;                   //如果深度相同且根节点不同,则新的根节点的深度+1
}

为什么+1?
在这里插入图片描述
合并完
在这里插入图片描述
显然+1

例题代码:

#include <cstdio>
#define MAXN 5005
int fa[MAXN], rank[MAXN];
inline void init(int n)
{for (int i = 1; i <= n; ++i){fa[i] = i;rank[i] = 1;}
}
int find(int x)
{return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
inline void merge(int i, int j)
{int x = find(i), y = find(j);if (rank[x] <= rank[y])fa[x] = y;elsefa[y] = x;if (rank[x] == rank[y] && x != y)rank[y]++;
}
int main()
{int n, m, p, x, y;scanf("%d%d%d", &n, &m, &p);init(n);for (int i = 0; i < m; ++i){scanf("%d%d", &x, &y);merge(x, y);}for (int i = 0; i < p; ++i){scanf("%d%d", &x, &y);printf("%s\n", find(x) == find(y) ? "Yes" : "No");}return 0;
}

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

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

相关文章

STM32控制数码管从0显示到99

首先 先画电路图吧&#xff01;打开proteus&#xff0c;导入相关器件&#xff0c;绘制电路图。如下&#xff1a;&#xff08;记得要保存啊&#xff01;发现模拟一遍程序就自动退出了&#xff0c;有bug&#xff0c;我是解决不了&#xff0c;所以就是要及时保存&#xff0c;自己重…

猫头虎分享已解决Bug || ModuleNotFoundError: No module named ‘tensorflow‘

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

crmeb多门店商城系统二次开发 增加车辆车牌搜索功能、车辆公里数

1、增加的数据库 ALTER TABLE eb_store_order ADD cart_number VARCHAR(255) NOT NULL DEFAULT COMMENT 车牌 AFTER erp_order_id, ADD curmileage VARCHAR(255) NOT NULL DEFAULT COMMENT 当前里程 AFTER cart_number; ALTER TABLE eb_store_cart ADD cart_number VARCHAR(…

【Git企业实战开发】Git常用开发流操作总结

【Git企业实战开发】Git常用开发流操作总结 大家好 我是寸铁&#x1f44a; 总结了一篇Git常用开发流操作总结的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 现在刚做项目的伙伴&#xff0c;可能你之前学过git&#xff0c;但是一实战发现不熟悉 没关系&#xff0c;看寸铁这篇…

核密度分析

一.算法介绍 核密度估计&#xff08;Kernel Density Estimation&#xff09;是一种用于估计数据分布的非参数统计方法。它可以用于多种目的和应用&#xff0c;包括&#xff1a; 数据可视化&#xff1a;核密度估计可以用来绘制平滑的密度曲线或热力图&#xff0c;从而直观地表…

力扣基础刷题---二分查找

704. 二分查找 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 中心思想&#xff1a;找到中间值&#xff0c;跟中间值比…

新版Java面试专题视频教程——虚拟机篇②

新版Java面试专题视频教程——虚拟机篇② 3 垃圾收回3.1 简述Java垃圾回收机制&#xff1f;&#xff08;GC是什么&#xff1f;为什么要GC&#xff09;3.2 对象什么时候可以被垃圾器回收3.2.1 引用计数法3.2.2 可达性分析算法 3.3 JVM 垃圾回收算法有哪些&#xff1f;——4种3.3…

聊聊mysql的七种日志

进入正题前,可以先简单介绍一下,MySQL的逻辑架构, MySQL的逻辑架构大致可以分为三层: 第一层:处理客户端连接、授权认证,安全校验等。第二层:服务器 server 层,负责对SQL解释、分析、优化、执行操作引擎等。第三层:存储引擎,负责MySQL中数据的存储和提取。我们要知道…

QT day2 2.21

1.使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 代码&#xff1a; #include "mywidget.h" #include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(pa…

vue基础操作(vue基础)

想到多少写多少把&#xff0c;其他的想起来了在写。也写了一些css的 input框的双向数据绑定 html <input value"123456" type"text" v-model"account" input"accou" class"bottom-line bottom" placeholder"请输入…

【Vuforia+Unity】AR05-实物3D模型识别功能实现(ModelTarget )

不管是什么类型的识别Vuforia的步骤基本都是: 把被识别的物体转成图、立体图、柱形图,3D模型、环境模型,然后模型生成Vuforia数据库-导入Unity-参考模型位置开始摆放数字内容,然后参考模型自动隐藏-发布APP-识别生活中实物-数字内容叠加上去! 对于3D物体的识别,可以是虚…

C语言:指针(一)

目录 1.内存和地址2. 指针变量和地址2.1 取地址操作符&#xff08;&&#xff09;2.2 指针变量和解引用操作符&#xff08;*&#xff09;2.2.1 指针变量2.2.2 解引用操作符&#xff08;*&#xff09; 2.3 指针变量的大小 3.指针变量的类型和意义3.1 指针的解引用3.2 指针 -指…

消息中间件篇之RabbitMQ-消息重复消费

一、导致重复消费的情况 1. 网络抖动。 2. 消费者挂了。 消费者消费消息后&#xff0c;当确认消息还没有发送到MQ时&#xff0c;就发生网络抖动或者消费者宕机。那当消费者恢复后&#xff0c;由于MQ没有收到消息&#xff0c;而且消费者有重试机制&#xff0c;消费者就会再一次消…

搜维尔科技:【周刊】适用于虚拟现实VR中的OptiTrack

适用于 VR 的 OptiTrack 我们通过优化对虚拟现实跟踪最重要的性能指标&#xff0c;打造世界上最准确、最易于使用的广域 VR 跟踪器。其结果是为任何头戴式显示器 (HMD) 或洞穴自动沉浸式环境提供超低延迟、极其流畅的跟踪。 OptiTrack 主动式 OptiTrack 世界领先的跟踪精度和…

【PostgreSQL实现psql连接时候提示用户的密码有效时间】

如下内容使用session_exec插件结合自定函数实现。类似于触发器的原理。 功能需要严格在测试环境测试后&#xff0c;才可在正式环境使用。没有相关要求&#xff0c;还是建议直接查询pg_roles/pg_authid/pg_user&#xff1b; 一、判断是否需要修改用户密码和有效期的检查SQL 首…

Linux: yum查看、安装、删除软件包

Linux: yum安装删除软件包 yum查找软件包yum 安装软件yum 卸载软件 yum查找软件包 在Linux中提供一条yum list指令用于查看当前系统中已存在和可以安装的软件包&#xff0c;但由于软件包的数量过多&#xff0c;所以我们可以通过grep指令来过滤出我们需要查找的软件包。 yum l…

初识Linux

操作系统的概念&#xff1a; 计算机由哪两个部分组成&#xff1f; 硬件和软件 操作系统是什么&#xff1f;由什么作用&#xff1f; 操作系统识软件的一类。 主要是协助用户调度硬件工作&#xff0c;充当用户和计算机硬件之间的桥梁 操作系统控制微信发消息的原理&#xf…

Linux系列讲解 —— 【Vim编辑器】在Ubuntu18.04中安装新版Vim

平时用的电脑系统是Ubuntu18.04&#xff0c;使用apt安装VIM的默认版本是8.0。如果想要安装新版的Vim编辑器&#xff0c;只能下载Vim源码后进行编译安装。 目录 1. 下载2. 编译3. 安装4. 遇到的问题4.1 打开vim后&#xff0c;文本开头有乱码现象。4.2 在Vim编辑器中&#xff0c;…

Python炒股自动化(2):获取股票实时数据和历史数据

如果你是一位大佬&#xff0c;看我前面的分享即可&#xff0c;相信你有自己的思路&#xff0c;或者已经有了成熟的策略&#xff0c;你需要的只是API接口来实现你的想法&#xff0c;前面的分享是你需要的&#xff0c;这些是给刚开始接触程序交易的朋友分享的。 前面发了股票程序…

YOLOv5算法进阶改进(17)— 添加BiFormer注意力机制 | 提升小目标检测精度

前言:Hello大家好,我是小哥谈。本文主要通过对YOLOv5模型添加Bifommer注意力机制为例,让大家对于YOLOv5模型添加注意力机制有一个深入的理解,通过本文你不仅能够学会添加Biformer注意力机制,同时可以举一反三学会其他的注意力机制的添加。🌈 前期回顾: YOLOv5算法进…
推荐文章