编程奇境:C++之旅,从新手村到ACM/OI算法竞赛大门(中级武器:并查集)

我们都知道,朋友的朋友也可以是朋友,并查集就是这么一种武器,能够让自己广交天下之友。

并查集

并查集啊,想象一下你班上的同学们都在操场上自由活动。突然老师说:"大家找朋友手拉手围成圈玩个游戏!"这时候,每个同学就得赶紧找到其他同学牵手,形成一个个的小圈子。

一开始,可能有的同学很快就找到了朋友,两个人就形成了一个小小的圈子;有的同学可能慢一点,但他们最终也会找到别人,加入到已有的圈子或者和新找到的朋友形成新的圈子。在这个过程中,如果两个小圈子碰到了,他们就可以选择合并成一个更大的圈子。

并查集,就是在计算机里帮助我们管理这种"找朋友拉手组成圈子"的一种数据结构。它主要有两个任务:一个是"查询"(find),就是看看某个同学属于哪个圈子;另一个是"合并"(union),就是把两个圈子合在一起变成一个大圈子。

举个例子,假如你想要知道小明和小红是不是在一个圈子里玩,你就可以用并查集的"查询"功能,很快得出答案。如果小明和小红不在同一个圈子里,但你想让他们一起玩,就可以用"合并"功能,让他们的圈子连起来。

简单来说,并查集就像是一个班级里的"牵手管理员",帮助我们知道谁和谁是一伙的,还能轻松地把不同的小组组合成更大的团队,特别适合处理一些需要不断合并和查询团体归属的问题。

举个栗子

第一行包含两个整数 𝑁,𝑀,表示共有 𝑁个元素和 𝑀个操作。

接下来 𝑀行,每行包含三个整数 𝑍𝑖,𝑋𝑖,𝑌𝑖​。

当 𝑍𝑖=1时,将 𝑋𝑖与 𝑌𝑖所在的集合合并。

当 𝑍𝑖=2 时,输出 𝑋𝑖与 𝑌𝑖是否在同一集合内,是的输出 Y ;否则输出 N

cpp 复制代码
#include<iostream>
using namespace std;
int f[200005];
//并查集模板 
int find(int x)
{
	if (f[x] == x)//如果组长是自己 
	{
		return x;//直接返回 
	}
	f[x] = find(f[x]);//递归地找组长 
	return f[x];
}
void merge(int u, int v)//合并 
{
	f[v] = u;//把v这个组归到u这个组里 
}
int main()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		f[i] = i;//初始化 每个人的组长都是自己 
	}
	for (int i = 0; i < m; i++)
	{
		int z;
		int x, y;
		cin >> z >> x >> y;
		int u = find(x);//寻找组长 
		int v = find(y);
		if (z == 1)//如果可以合并 
		{
			merge(u, v);
		}
		else if (z == 2)//查找 
		{
			if (find(x) == find(y)) {//看看是否是同一个组的 
				cout << "Y" << endl;
			}
			else
			{
				cout << "N" << endl;
			}
		}
	}
	return 0;
}

应用场景

并查集这种数据结构虽然简单,但它在很多实际问题中非常有用,尤其擅长处理涉及分类、归属判断和动态集合合并的问题。以下是并查集的一些典型应用场景:

  1. 社交网络的朋友圈问题:在社交网络中,如果要判断两个人是否是朋友或者间接朋友(通过共同的朋友连接),可以使用并查集来高效地管理和查询这些关系。

  2. 图的连通性问题:在无向图中,判断两个顶点是否连通,或者统计连通分量的数量时,可以用并查集快速实现。

  3. 赛事安排问题:如果有比赛需要避免某些特定队伍在早期相遇(比如来自同一地区的队伍),可以通过构建并查集来确保不会安排这样的对阵。

  4. 文件系统管理:在操作系统中,用来管理文件和目录的层次结构,判断两个文件是否位于同一个目录下。

  5. 最小生成树算法中的 Cycle Detection(环检测):如Kruskal算法中,用于检测添加一条边是否会形成环。

  6. 游戏开发中的团队管理:在多人在线游戏中,快速合并和查询玩家的队伍状态。

  7. 文本处理中的名词消歧:在自然语言处理中,识别文本中的名词是否指代同一实体,有助于实现命名实体识别的优化。

  8. 网络路由问题:在网络设计中,确定数据包从源到目的地是否有可达路径,或者在路由表合并时避免循环。

并查集的高效之处在于它支持近乎常数时间的查询和合并操作,这使得它成为解决上述问题的有力工具。在很多情况下,通过巧妙地使用并查集,可以大大简化算法的设计和实现。

练习题

P3367 【模板】并查集 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P1551 亲戚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P1111 修复公路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P1195 口袋的天空 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P1396 营救 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P1892 [BOI2003] 团伙 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P1621 集合 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P2294 [HNOI2005] 狡猾的商人 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

百看不如一练,只有实践才是进步最快的方式,更要独立思考,如果想不出来了就看题解,会有眼前一亮的感觉。好啦,今天就到这里吧。下一期再见,记得给专栏点个关注,明天接着来哦~

相关推荐
A懿轩A7 分钟前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
古希腊掌管学习的神8 分钟前
[搜广推]王树森推荐系统——矩阵补充&最近邻查找
python·算法·机器学习·矩阵
云边有个稻草人12 分钟前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法
机器视觉知识推荐、就业指导12 分钟前
C++设计模式:享元模式 (附文字处理系统中的字符对象案例)
c++
半盏茶香12 分钟前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
忘梓.1 小时前
解锁动态规划的奥秘:从零到精通的创新思维解析(3)
算法·动态规划
Evand J1 小时前
LOS/NLOS环境建模与三维TOA定位,MATLAB仿真程序,可自定义锚点数量和轨迹点长度
开发语言·matlab
LucianaiB1 小时前
探索CSDN博客数据:使用Python爬虫技术
开发语言·爬虫·python
️南城丶北离1 小时前
[数据结构]图——C++描述
数据结构··最小生成树·最短路径·aov网络·aoe网络
Ronin3051 小时前
11.vector的介绍及模拟实现
开发语言·c++