超级简单并查集详解

article/2025/8/26 23:56:33

一、概述

并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。

其实说白了大部分还是用于寻找两个点是否联通,求最小生成树。

二、分析

1、背景阐明

首先我们需要先阐明一个简单的道理,假如从A城能到B城,从B城能到C城,那么自然A城和C城联通。并查集便是基于这个理论。

举个例子,在某黑厂中,员工们吃饭时往往三两成群(每个小群体都有一个比较有主见的人决定中午吃什么,当然,两个很主见的人不可能在一个小集体,但是有的可能仅仅是为了和朋友在一起,并不关心到底吃什么),比如志熊喜欢拉上员工小C一起出去吃,gmk喜欢和whr、rzw三人在食堂解决,而xuao恩自己带饭。于是大概就变成了这样一张图:

(头上原谅星的是这个团队里的主心骨) 

2、查找

假如说员工小C的外校朋友小D想和小C一起吃个饭追溯一下革命友情(手动滑稽),他会找小C这个集团的主心骨协商会面,很可惜,小C不是这个集团的主心骨,那如何找到呢?

闲话不多说,直接上代码来理解。

我们定义一个find函数和一个数组f[ ](用来记录他“想跟随”的朋友)。

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

3、合并 

有一天,员工小C跟随的好友志熊觉得 跟学长lyb和dhy混也不错,于是他们决定加入他们。

于是图变成了这样:

志熊决定跟随学长dhy,所以吃什么已经不由他来决定了(头上的原谅星也随之消失),如图志熊选择跟随dhy,小C认为还是和朋友在一起好,也会跟随志熊,lyb如常跟随dhy,这样新的四人团体就构成了。 

然而代码如何实现呢,这非常简单:

void join(int x,int y)
{father[find(x)]=find(y);
}

4、路径压缩 

员工小C有一天突然觉得 和学长密切交流的机会 不能全给志熊啊,他决定直接跟随学长dhy,不再跟随志熊了。

如下图所示:

而这一步代码如何实现呢:

int zip(int x)//路径压缩
{if(pre[x]!=x)//如果它的前驱节点不是他自己//(他不是这个小团体的主心骨) pre[x]=find(pre[x]);//他直接跟随老大 return x;
}​

 我们可以看到经过路径压缩的节点及其子树到根节点的深度减小了很多,所以在以后的操作中,查找根节点的速度会快很多,这就是路径压缩的意义。

5、按秩排序

zsy看到了两个集团的合并,决定也加入他们,此时zsy有一个伙伴,而dhy有三个。人多力量大么,自然人少了要向人多的靠拢,如图所示:

上代码:

void unionn(int r1,int r2)//秩排序 rank用来记录随从的多少 
{int fr1=find(r1);//找到r1团队的主心骨 int fr2=find(r2);//找到r2团队的主心骨 if(fr1==fr2)//自己人,走吧 return;if(rank[fr1]>=rank[fr2])//r1的人多 {f[fr2]=fr1;//r2成为r1的一部分 rank[fr1]+=rank[fr2];//r1多了很多"随从" }else//r2的人多{f[fr1]=fr2;//r1成为r2的一部分 rank[fr2]+=rank[fr1];//r2多了很多"随从" }
}

当然每次别忘了 把rank数组初始化(在输入的同时)

对于并查集来说,这是一种优化,将小树移到大树上,可以有效降低整个树的深度。

6、并查反集

我也是才发现了这个问题

 [BOI2003]团伙 

题目描述
给定 nn 个人,他们之间有两个种关系,朋友与敌对。可以肯定的是:与我的朋友是朋友的人是我的朋友
与我敌对的人有敌对关系的人是我的朋友
现在这 nn 个人进行组团,两个人在一个团队内当且仅当他们是朋友。求最多的团体数。输入格式
第一行一个整数 nn 代表人数。
第二行一个整数 mm 代表每个人之间的关系。
接下来 mm 行每行一个字符 optopt 与两个整数 p,qp,q如果 optopt 为 F 代表 pp 与 qq 为朋友。
如果 optopt 为 E 代表 pp 与 qq 为敌人。
输出格式
一行一个整数代表最多的团体数。输入输出样例
输入 #1复制
6
4
E 1 4
F 3 5
F 4 6
E 1 2
输出 #1复制
3
说明/提示
对于 100\%100% 的数据,2 \le n \le 10002≤n≤1000,1 \le m \le 50001≤m≤5000,1 \le p,q \le n1≤p,q≤n。
#include<bits/stdc++.h>
using namespace std;
int s,n,m,a,b,f[2500];
char ch;
int find(int x){if(f[x]!=x)f[x]=find(f[x]);//查找+路径压缩,如果没有祖先就回溯return f[x];
}
int main(){cin>>n>>m;for(int i=1;i<=2*n;i++){f[i]=i;//初始化,千万不能漏}for(int i=1;i<=m;i++){cin>>ch>>a>>b;if(ch=='F'){f[find(a)]=find(b);//合并}else{f[find(a+n)]=find(b);//printf("<%d的父亲是%d>\n",find(a+n),find(b)) ;f[find(b+n)]=find(a);//printf("<%d的父亲是%d>\n",find(b+n),find(a)) ;//反集合并}}for(int i=1;i<=n;i++){if(f[i]==i)s+=1;}cout<<s;//祖先数就是团伙数
}

当a与b结仇,相当于黑化a的大哥是b。之后a又与c结仇,此时黑化a的大哥是b,并查集一下,b的大哥就成了c。


http://chatgpt.dhexx.cn/article/0GBOJHQp.shtml

相关文章

并查集(java)

介绍 &#xff1a; 并查集属于数据结构的一种 是高等数据结构最基础的一部分&#xff0c;主要分为普通并查集 种类并查集以及带权并查集。它是一种用于管理元素所属集合的数据结构&#xff0c;这里的集合我们可以理解为一颗数 每个元素都是树上的有一个分叉&#xff0c;顺着分叉…

C++并查集

文章目录 并查集的原理并查集的实现代码并查集的典型应用 并查集的原理 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合。开始时&#xff0c;每个元素自成一个单元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用…

c++并查集(详细总结)

老话重谈&#xff0c;先看定义 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合&#xff08;disjoint sets&#xff09;的合并及查询问题。常常在使用中以森林来表示。 首先得明白一些概念&#xff1a; 什么是树&#xff0c;什么是森林&#xff08;由树组成的叫…

Java——并查集

概念 当我们将多个元素分配到不同的集合中&#xff0c;这些集合有的是相关的&#xff0c;有的是不相关的。并查集就是用来查找两个元素是否在同一个集合中的 其主要实现方式是&#xff1a;将所有的元素以下标的形式存储在数组中。例如一共有十个人&#xff0c;那么就将这些人…

并查集Python版

以下来自于leetcode 使用数据结构&#xff1a;并查集 思路&#xff1a;由于相等关系具有传递性&#xff0c;所有相等的变量属于同一个集合&#xff1b;只关心连通性&#xff0c;不关心距离&#xff0c;因此很容易想到并查集。&#xff08;很容易嘛&#xff0c;反正我想不到&am…

并查集详解

文章目录 并查集一、简介1.定义2. 并查集的实现与优化 二、练习1.合并集合2.连通块中点的数量3. 食物链 三、总结 并查集 一、简介 1.定义 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合的合并及查询问题&#xff08;即所谓的并、查&#xff09;。比如说&am…

带权并查集

带权并查集需要先理解一般的并查集&#xff0c;不明白的可自行先搜索有关内容 一般的并查集主要记录节点之间的链接关系&#xff0c;而没有其他的具体的信息&#xff0c;仅仅代表某个节点与其父节点之间存在联系&#xff0c;它多用来判断图的连通性&#xff0c;如下图所示&…

并查集,不就一并和一查?

什么是并查集 并查集这种数据结构&#xff0c;可能出现的频率不是那么高&#xff0c;但是还会经常性的见到&#xff0c;其理解学习起来非常容易&#xff0c;通过本文&#xff0c;一定能够轻轻松松搞定并查集&#xff01; 对于一种数据结构&#xff0c;肯定是有自己的应用场景和…

数据结构——并查集

并查集是一种数据结构&#xff0c;是树的一种应用&#xff0c;用于处理一些不交集&#xff08;一系列没有重复元素的集合&#xff09;的合并以及查询问题。并查集支持如下操作&#xff1a; 查询&#xff1a;查询某个元素属于哪个集合&#xff0c;通常是返回集合内的一个“代表…

并查集详解(C/C++)

并查集算法详解&#xff08;C&#xff09; 并查集基础并查集是什么&#xff1f;并查集的作用是什么&#xff1f;并查集的结构合并查询 代码实现优化1&#xff1a;避免退化&#xff08;按秩合并&#xff09;代码优化 优化2&#xff1a;路径压缩代码优化 最终代码实现复杂度分析经…

并查集及其应用

并查集的基本操作: 1.合并两个集合 2.查询两个元素的祖宗节点 扩展: 1.记录每个集合的大小 将集合大小绑定到代表元素节点上 就是并查集的思想 (不是每个元素都是正确的 但是代表元素是正确的) 2.记录每个点到根节点的距离 绑定到每个元素身上 因为每个元素到根节点的距离…

并查集(Union-Find) (图文详解)

文章目录 并查集基础知识定义C实现优化 精选算法题(Java实现)实现并查集交换字符串中的元素最长连续序列 - 字节面试常考连通网络的操作次数最大岛屿数量 (三种解法)省份数量冗余连接冗余连接Ⅱ情侣牵手(困难)移除最多的同行或同列石头等式方程的可满足性 结语 并查集基础知识 …

什么是 “并查集” ?

导语&#xff1a;并查集是一种精巧的算法&#xff0c;本身并不难理解&#xff0c;却很常用&#xff0c;在许多场景下都能找到并查集的身影。 本文作者封承成&#xff0c;年仅12岁&#xff0c;非常感谢他的投稿。 并查集是什么 并查集&#xff0c;是一种判断“远房亲戚”的算法。…

并查集(Disjoint Set)

目录 ❤️什么是并查集&#xff1f; &#x1f3b6;实现方法1 &#x1f414;实现方法2 &#x1f383;题目1 ❤️什么是并查集&#xff1f; 并查集是一种数据结构&#xff0c;用于处理一些不交集&#xff08;Disjoint sets&#xff0c;一系列没有重复元素的集合&#xff09;的…

并查集

参考 https://www.cnblogs.com/asdfknjhu/p/12515480.html https://www.bilibili.com/video/BV13t411v7Fs?p3 https://leetcode-cn.com/problems/number-of-provinces/solution/python-duo-tu-xiang-jie-bing-cha-ji-by-m-vjdr/ 一、基本概念 并查集是一种数据结构 并查集这…

并查集(详细解释+完整C语言代码)

目录 1概论 2.树的表现形式 3.代码实现 3.1创立集合 3.2合并 3.3查询 3.4路径压缩 第一个方法&#xff1a;查找时优化 第二个方法&#xff1a;合并时优化&#xff08;加权标记法&#xff09; 4.完整代码 4.1优化前 4.2优化后 1概论 并查集是一种十分精巧且实用的树形…

时间序列预测的一般步骤

一、ARIMA模型概述 ​​ ARMA模型就是AR和MA的简单结合&#xff0c;同时包含了历史数值项和错误项。由于AR和MA模型都对时间序列有平稳性要求&#xff0c;ARMA模型也存在这个限制&#xff0c;因此我们将其拓展到ARIMA模型&#xff0c;其可以解决非平稳性问题。引入的差分概念是…

时间序列预测算法总结

时间序列算法 time series data mining 主要包括decompose&#xff08;分析数据的各个成分&#xff0c;例如趋势&#xff0c;周期性&#xff09;&#xff0c;prediction&#xff08;预测未来的值&#xff09;&#xff0c;classification&#xff08;对有序数据序列的feature提…

基于深度学习的时间序列预测

# 技术黑板报 # 第十一期 推荐阅读时长&#xff1a;15min 前言 时间序列建模历来是学术和工业界的关键领域&#xff0c;比如用于气候建模、生物科学和医学等主题应用&#xff0c;零售业的商业决策和金融等。虽然传统的统计方法侧重于从领域专业知识层面提供参数模型&#xff0…

预测类问题中的时间序列预测模型

前言&#xff1a;时间序列预测模型适用于含有时间变量的模型预测&#xff0c;对中短期的预测有着较好的结果&#xff0c;对长期预测不适用。本文重点介绍ARIMA模型的原理及代码实现。 其他模型总结&#xff1a;​【Python】Python中的经典时间序列预测模型总结_风度78的博客-C…