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

图论——并查集

参考内容:

图论——并查集(详细版)

并查集(Disjoint-set)是一种精巧的树形数据结构,它主要用于处理一些不相交集合的合并及查询问题。一些常见用途,比如求联通子图、求最小生成树的 Kruskal 算法和求最近公共祖先(LCA)等。

并查集的理念是只关注个体属于哪个阵营,并不关心这个阵营中个体内部的关系,比如我们常说的张三是李家沟的,王二是王家坝的。同时并查集借助个体代表集体的思想,用一个元素代表整个群体,就像我们开学都会有学生代表、教师代表讲话一样,在台上讲话的那一个学生就代表了学校所有的学生。

并查集基本操作

并查集的基本操作主要有初始化 init查询 find合并 union操作。

初始化

在使用并查集的时候,常常使用一个数组fa来存储每个元素的父节点,在一开始的时候所有元素与其它元素都没有任何关系,即大家相互之间还不认识,所以我们把每个元素的父节点设为自己。

#define ARR_LEN 6000int fa[ARR_LEN];void init(int n)
{for(int i = 1; i <= n; i++)fa[i] = i;
}

查询

查询即找到指定元素的祖先。需要注意的是,这里我们需要找到指定元素的根祖先,不能找到爸爸或者爷爷就停止了,而是要找到查找不下去了为止,所以要不断的去递归下去,直到找到父亲为自己的结点才结束。

int find(int i)
{if(i == fa[i]) // 递归出口return i;elsereturn find(fa[i]); // 不断向上查找祖先
}

考虑下面的场景,假如第一次我们需要查询元素5的祖先,第二次需要查询元素4的祖先,会发现第一次查询包含了第二次查询的计算过程,但我们的程序却傻傻的计算了两次,有没有办法去来优化查询过程,让每一次查询都能利用到此前查询计算的便利?

考虑到并查集并不关心某个元素的爸爸、爷爷是谁,只关心最终的祖先是谁,所以我们可以在查询的过程中顺便做一些修改,比如在查询5的过程中,顺便就把42的父亲给修改为1,即我们在查找过程中进行路经压缩

int find(int i)
{if(i == fa[i]){return i;} else {fa[i] = find(fa[i]); // 进行路径压缩return fa[i];}
}

合并

合并操作即介绍两个人相互认识,将他们纳入同一个帮派,只需要将俩元素的父亲修改为同一个即可。

void union(int i, int j)
{int fa_i = find(i);int fa_j = find(j);fa[fa_i] = fa_j;
}

相关练习题目

洛谷 P1551 亲戚

题目连接:https://www.luogu.com.cn/problem/P1551

题目描述

若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。

规定: x x x y y y 是亲戚, y y y z z z 是亲戚,那么 x x x z z z 也是亲戚。如果 x , y x,y xy 是亲戚,那么 x x x 的亲戚都是 y y y 的亲戚, y y y 的亲戚也都是 x x x 的亲戚。

输入格式

第一行:三个整数 n , m , p , ( n , m , p ≤ 5000 ) n,m,p,(n,m,p≤5000) n,m,p(n,m,p5000) 分别表示有 n n n 个人, m m m 个亲戚关系,询问 p p p 对亲戚关系。

以下 m m m 行:每行两个数 M i , M j , 1 ≤ M i , M j ≤ n M_i,M_j,1≤M_i,M_j≤n MiMj1MiMjn,表示 M i M_i Mi M j M_j Mj 具有亲戚关系。

接下来 p p p 行:每行两个数 P i , P j P_i,P_j PiPj,询问 P i P_i Pi P j P_j Pj 是否具有亲戚关系。

输出格式

p p p 行,每行一个YesNo。表示第 i i i 个询问的答案为“具有”或“不具有”亲戚关系。

输入输出样例
# 输入
6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6# 输出
Yes
Yes
No
题目解析

可以发现这是一个非常标准的并查集问题,简直和并查集模版如出一辙,因此直接将所有关系读取后进行合并,然后直接查询父亲是否为同一个即可。

#include<bits/stdc++.h>
using namespace std;#define ARR_LEN 6000int fa[ARR_LEN];void init(int n)
{for(int i = 1; i <= n; i++)fa[i] = i;
}int find(int i)
{if(i == fa[i]){return i;} else {fa[i] = find(fa[i]);return fa[i];}
}void union(int i, int j)
{int fa_i = find(i);int fa_j = find(j);fa[fa_i] = fa_j;
}int main()
{int n, m, p;int a, b;cin>> n >> m >> p;init(n);for(int i = 0; i < m; i++){cin >> a >> b;union(a, b);}for(int i = 0; i < p; i++){cin >> a >> b;int fa_a = find(a);int fa_b = find(b);if(fa_a == fa_b)cout<<"Yes"<<endl;elsecout<<"No"<<endl;}
}

杭电 OJ1213 How Many Tables

题目连接:https://acm.hdu.edu.cn/showproblem.php?pid=1213

题目描述

Today is Ignatius’ birthday. He invites a lot of friends. Now it’s dinner time. Ignatius wants to know how many tables he needs at least. You have to notice that not all the friends know each other, and all the friends do not want to stay with strangers.

One important rule for this problem is that if I tell you A knows B, and B knows C, that means A, B, C know each other, so they can stay in one table.

For example: If I tell you A knows B, B knows C, and D knows E, so A, B, C can stay in one table, and D, E have to stay in the other one. So Ignatius needs 2 tables at least.

输入格式

The input starts with an integer T ( 1 < = T < = 25 ) T(1<=T<=25) T(1<=T<=25) which indicate the number of test cases. Then T T T test cases follow. Each test case starts with two integers N N N and M ( 1 < = N , M < = 1000 ) M(1<=N,M<=1000) M(1<=N,M<=1000). N N N indicates the number of friends, the friends are marked from 1 1 1 to N N N. Then M M M lines follow. Each line consists of two integers A A A and B ( A ! = B ) B(A!=B) B(A!=B), that means friend A A A and friend B B B know each other. There will be a blank line between two cases.

输出格式

For each test case, just output how many tables Ignatius needs at least. Do NOT print any blanks.

输入输出样例
# 输入
2
5 3
1 2
2 3
4 55 1
2 5# 输出
2
4
题目解析

分析可以发现,这个问题要我们做的是统计在所有元素合并之后,统计总共有多个和集合。很轻松就能写出下面的 AC 代码。类似的问题还有杭电 OJ1232 畅通工程。

读者大人可以在此基础上继续进行延伸,我们实际生活中每个桌子只能坐 8 个人,假设还需要考虑每桌人数的容量,又如何进行改进呢?

#include<bits/stdc++.h>
using namespace std;#define ARR_LEN 6000int fa[ARR_LEN];void init(int n)
{for(int i = 1; i <= n; i++)fa[i] = i;
}int find(int i)
{if(i == fa[i]){return i;} else {fa[i] = find(fa[i]);return fa[i];}
}void union(int i, int j)
{int fa_i = find(i);int fa_j = find(j);fa[fa_i] = fa_j;
}int main()
{int n, m, a, b, t;cin>>t;for(int i = 0; i < t; i++){cin>>n>>m;int ans = 0;init(n);for(int i = 0; i < m; i++) {cin>>a>>b;union(a, b);}for(int i = 1; i <= n; i++) {// 如果父亲是自己,那么就表示一个独立的集合if(find(i) == i)ans++;}cout<<ans<<endl;}}

杭电 OJ1272 小希的迷宫

题目连接:https://acm.hdu.edu.cn/showproblem.php?pid=1272

题目描述

小希设计了一个迷宫让 Gardon 玩,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间 A 和 B,那么既可以通过它从房间 A 走到房间 B,也可以通过它从房间 B 走到房间 A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从 5 到达 8。

输入格式

输入包含多组数据,每组数据是一个以 0 0 结尾的整数对列表,表示了一条通道连接的两个房间的编号。房间的编号至少为 1,且不超过 100000。每两组数据之间有一个空行。整个文件以两个 -1 结尾。

输出格式

对于输入的每一组数据,输出仅包括一行。如果该迷宫符合小希的思路,那么输出Yes,否则输出No

输入输出样例
# 输入
6 8  5 3  5 2  6 4
5 6  0 08 1  7 3  6 2  8 9  7 5
7 4  7 8  7 6  0 03 8  6 8  6 4
5 3  5 6  5 2  0 0-1 -1# 输出
Yes
Yes
No
题目解析

其实这个问题就是让我们判断一个连通图中是否存在环,那么问题就转换为寻找出现环的条件。其实不难发现出现下面两种情况时,连通图即存在环。

  1. 在查找过程中,发现两个不同元素的父亲是相同的;
  2. 若不存在环,则边的数量一定比顶点数量少 1。
#include<bits/stdc++.h>
using namespace std;#define ARR_LEN 100010int fa[ARR_LEN];
bool visited[ARR_LEN]; // 用于辅助记录顶点的数量
int edges, points; // 记录顶点和边的数量
bool hascycle; // 是否存在环void init()
{hascycle = false;edges = 0;points = 0;for(int i = 1; i < ARR_LEN; i++)fa[i] = i, visited[i] = false;
}int find(int i)
{if(i == fa[i]){return i;} else {fa[i] = find(fa[i]);return fa[i];}
}void union(int i, int j)
{int fa_i = find(i);int fa_j = find(j);// 两个元素祖先相同,存在环if(fa_i == fa_j) {hascycle = true;} else {visited[i] = true;visited[j] = true;edges++;fa[fa_i] = fa_j;}
}int main()
{int a, b;init();while(cin>>a>>b) {if(a == 0 && b == 0) {cout<<"Yes"<<endl;continue;}if(a == -1 && b == -1) {return 0;}union(a, b);while(cin>>a>>b){if(a == 0 && b == 0) {break;}union(a, b);}if(hascycle) {cout<<"No"<<endl;continue;}for(int i = 1; i < ARR_LEN; i++){if(visited[i]) {points++;}}if(points == edges + 1) {cout<<"Yes"<<endl;} else {cout<<"No"<<endl;}init();}
}

相关文章:

图论——并查集

参考内容&#xff1a; 图论——并查集(详细版) 并查集&#xff08;Disjoint-set&#xff09;是一种精巧的树形数据结构&#xff0c;它主要用于处理一些不相交集合的合并及查询问题。一些常见用途&#xff0c;比如求联通子图、求最小生成树的 Kruskal 算法和求最近公共祖先&…...

计算机毕业设计java+vue+springboot的论坛信息网站

项目介绍 本论文系统地描绘了整个网上论坛管理系统的设计与实现&#xff0c;主要实现的功能有以下几点&#xff1a;管理员&#xff1b;首页、个人中心、用户管理、公告管理、公告类型管理、热门帖子管理、帖子分类管理、留言板管理、论坛新天地、我的收藏管理、系统管理&#…...

.net core添加SQL日志输出

GreDbContext : Microsoft.EntityFrameworkCore.DbContext 下添加 public static readonly ILoggerFactory MyLoggerFactory LoggerFactory.Create(builder > { builder.AddConsole(); }); protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder…...

虚幻5.1 常见的效果关闭方式

常见的虚幻效果关闭方式 1.Bloom ProjectSettings->Rendering->Default Settings->Bloom PostProcessVolume->Lens->Bloom 2.Ambient Occlusion/Screen Space Ambient Occlusion(SSAO) ProjectSettings->Rendering->Default Settings->Ambient Occl…...

每日一题 --- 力扣318----最大单词长度乘积

这道题时间复杂度我感觉设置的不是很好&#xff0c;应该最好是有一个1000变成10000就行。 因为我在做这道题的时候被误导了&#xff0c;以为双重循环暴力判断一下也能过&#xff0c;因为1000*1000 *26的时间复杂度没有到1亿&#xff0c;那么我刚开始认为是能过的&#xff0c;结…...

掌动智能性能压力测试优势有哪些

企业通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。本文将介绍性能压力测试的价值及主要优势! 一、性能压力测试的价值 1、评估系统能力&#xff1a;有助于参数的基准测试&#xff0c;可以度量系统的响应时间;还有助于检查系统是否可…...

虚拟机没有桥接模式--物理机WiFi不见了--注册表修复

我们知道虚拟机有三种模式&#xff1a; vmnet0 桥接模式&#xff1b;vmnet1 仅主机模式&#xff1b;vmnet8 NAT模式 我自己以前一直用的NAT模式&#xff0c;今天突然要用到桥接模式&#xff0c;发现无法切换... 我下面这个是后面弄好了的&#xff0c;最开始是没有显示桥接模式…...

【Python】批量下载素材酷视频资源

【需求】 做视频精彩需要用到梗图视频等,但是素材酷上面的视频没有搜索功能,每次用起来还要去下载也很麻烦,下载只能一个一个下载也很麻烦,下要搞一个能够批量下载的功能,然后把下载的资源全部放进万兴喵影编辑器的云空间,这样就可以做到随做随查随用了。 【效果】 目…...

QuantLib学习笔记——一个简单的价值估算案例

⭐️ 前言 QuantLib很强大&#xff0c;它实现了很多金融工具及其价值估算方法&#xff0c;从最简单的折现模型&#xff0c;到利用BSM模型对期权进行定价&#xff0c;覆盖面相当齐全。本文以一个简单的净现值估算案例&#xff0c;开启笔者金融工具估值的旅程。 开上豪车&#…...

智能语音和自然语言处理技术

一、定义 智能语音和自然语言处理技术是指通过计算机技术实现人机交互的一种技术。它可以让计算机和人类之间进行自然而流畅的交流&#xff0c;从而实现更高效、更便捷、更智能的信息交流和处理。 智能语音和自然语言处理技术主要包括语音识别、语音合成、自然语言理解、自然…...

【Sql】sql server数据库提示:执行Transact-SQL语句或批处理时发生了异常。 无法打开数据库msdb,错误:926。

【问题描述】 打开sql server2008r2数据库的时候&#xff0c; 系统提示执行Transact-SQL语句或批处理时发生了异常。 无法打开数据库msdb&#xff0c;错误&#xff1a;926。 【概念理解】 首先MSDB数据库是的作用&#xff1a; 用于给SQL Server代理提供必要的信息来运行调度警…...

Day 5 登录页及路由 (三) 基于axios的API调用

系列文章目录 本系列记录一下通过Abp搭建后端&#xff0c;VueElement UI Plus搭建前端&#xff0c;实现一个小型项目的过程。 Day 1 Vue 页面框架Day 2 Abp框架下&#xff0c;MySQL数据迁移时&#xff0c;添加表和字段注释Day 3 登录页以及路由 (一&#xff09;Day 4 登录页以…...

雷神学习---视音频数据处理入门:RGB、YUV像素数据处理

原文地址&#xff1a;https://blog.csdn.net/leixiaohua1020/article/details/50534150 ​​​​​​​​从代码可以看出&#xff0c;如果想把YUV格式像素数据变成灰度图像&#xff0c;只需要将U、V分量设置成128即可。 这是因为U、V是图像中的经过偏置处理的色度分量。色度分…...

Asp.Net Core服务端处理请求过来的压缩格式

之前是直接传没有经过压缩的文件字节&#xff0c;有时文件过大的话&#xff0c;可能占宽带就多&#xff0c;宽带流量都是钱。后来有个想法&#xff0c;在客户端把文件进行压缩&#xff0c;把压缩的文件流发给服务端进行解压。 1&#xff0c;先修改项目中Startup.cs文件中Confi…...

自定义指令

二、自定义指令 1.指令介绍 内置指令&#xff1a;v-html、v-if、v-bind、v-on… 这都是Vue给咱们内置的一些指令&#xff0c;可以直接使用 自定义指令&#xff1a;同时Vue也支持让开发者&#xff0c;自己注册一些指令。这些指令被称为自定义指令 每个指令都有自己各自独立的功…...

仿真实现lio_sam建图和ndt_matching定位

文章目录 一、仿真环境二、lio_sam建图1.修改配置文件2.开始建图 三、ndt_matching定位1.新建启动文件2.启动 总结 一、仿真环境 使用现有开源的仿真环境—从零开始搭建一台ROS开源迷你无人车&#xff0c;作者已经配置好小车模型以及gazebo环境&#xff0c;imu频率已改为200HZ…...

IDEA取消git对项目的版本控制

前言 前几天新建项目的时候不小心选了个git仓库&#xff0c;导致这个测试项目一直被git管理着。 解决办法 1 右键项目 选择打开资源目录 2 删除.git文件 把目录下的.git文件删掉 3 删除idea中的git管理 删除完.git文件后&#xff0c;进入idea&#xff0c;右下角会有这样的提…...

如何聪明地编写测试

作者&#xff5c;Maxim Schepelin Booking公司软件开发工程师 编译整理&#xff5c;TesterHome 以下为作者观点&#xff1a; 在我&#xff08;作者&#xff09;的职业生涯中&#xff0c;我多次看到团队如何开始自动化测试&#xff0c;当然并非所有尝试都成功。在这篇文章中…...

CF1866M Mighty Rock Tower

CF题面 luogu题面 期望题。 题目大意&#xff1a;一个人在搭积木&#xff0c;每次堆叠可能成功或失败&#xff0c;失败可能导致其下面连续的若干块掉落。给定搭每一块时失败的概率&#xff0c;求堆叠完成的期望次数。 具体的&#xff0c;假设当前正在堆叠第 i 块&#xff0c;…...

【漏洞复现】Apache_Tomcat7+ 弱口令 后台getshell漏洞

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证 说明内容漏洞编号漏洞名称Tomcat7 弱口令 && 后台getshell漏洞漏洞评级高…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

相关类相关的可视化图像总结

目录 一、散点图 二、气泡图 三、相关图 四、热力图 五、二维密度图 六、多模态二维密度图 七、雷达图 八、桑基图 九、总结 一、散点图 特点 通过点的位置展示两个连续变量之间的关系&#xff0c;可直观判断线性相关、非线性相关或无相关关系&#xff0c;点的分布密…...