首页 > 其他分享 >并查集(Union Find Set)

并查集(Union Find Set)

时间:2023-11-06 21:23:08浏览次数:33  
标签:pre return Union siz 查集 find int 节点 Find

1 基本介绍

并查集是一种用来判断两个元素之间是否有关系的集合。
它的基本思想为:对于两个元素,如果他们之间有关系,则将其连接,以此形成一颗树。
对于任意两个节点,如果它们有相同的根节点,则它们之间有关系。

2. 建立步骤

给定n个点,以及m个关系。

1. 初始状态

将每个节点的根节点都指向自己

for (int i = 0; i < n; i++) {
	pre[i] = i;
}

2. 建立关系

对于给定的两个节点,我们发现,如果要连接两个节点所在的树,只能改变根节点。所以,我们先构建方法寻找根节点,再将一颗树的根节点连接到另一棵树的根节点上。

int find(int x) {
//1. 递归方式
	return pre[x] == x ? x : find(pre[x])
//2. 非递归
	while(pre[x]^x) x = pre[x];
	return x;
}

连接函数

void merge(int x, int y) {
	x = find(x), y = find(y);
	pre[x] = y;
}

例题分析

来源:洛谷P3367

1. 并查集(无优化)

#include <iostream>
using namespace std;
const int N = 10e5 + 9;
int pre[N];
int find(int x) {
	while (pre[x] ^ x) x = pre[x];
	return x;
}
void merge(int x, int y) {
	x = find(x), y = find(y);
	pre[x] = y;
}
void solve() {
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < N; i++) pre[i] = i;
	while (m--) {
		int z, x, y;
		cin >> z >> x >> y;
		if (z == 1) {
			merge(x, y);
		} else {
			cout << (find(x) == find(y) ? 'Y' : 'N') << "\n";
		}
	}
}
int main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int _ = 1;
	while (_--) solve();
	return 0;
}

2. 路径压缩

当我们每一次查找x的根节点的时候,顺便将x的父节点的根节点也变成根节点,使得生成的树的形状又矮又胖。
只需要修改find函数

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

或者为使用两次while循环来改变。

3. 按秩合并

由上面的分析我们知道,如果是将一颗小树附加到一颗大树上面,那么在查找的过程中的复杂度会降低,以此,我们构建一个rank数组,初始值都为1,它记录这棵树的层数(只有根节点的数有效,毕竟我们只连接根节点)
注意,当我们使用按秩合并的时候,我们在查找的时候就不能进行路径压缩(这样会导致秩不断在改变,我尝试了一下一起使用,效果反而不如单个使用)。
修改的merge函数为:

void merge(int x, int y) {
	x = find(x), y = find(y);
	if (x == y) return;
	if (rnk[x] >= rnk[y]) pre[y] = x, rnk[x]++;
	else
		pre[y] = x, rnk[y]++;
}

4. 按大小合并

和秩一样,当一颗较小的树合并到另一棵较大的树的时候,形成的树会变得矮胖。因此,创建一个siz数组来储存每棵树的大小,初始值为1。和上面一样,只需要修改为:

void merge(int x, int y) {
	x = find(x), y = find(y);
	if (x == y) return;
	if (siz[x] >= siz[y]) pre[y] = x, siz[x] += siz[y];
	else
		pre[y] = x, siz[y] += siz[x];
}

标签:pre,return,Union,siz,查集,find,int,节点,Find
From: https://www.cnblogs.com/C-qian/p/17813684.html

相关文章

  • 2023-11-06 Could not find any Electron packages in devDependencies ==》没有安装E
    问题描述:electron项目安装好后,运行npmrunstart时报错。解决方案:npmielectron--save-dev推荐使用powershell终端来输入,如果你用的是vscode的终端会出现卡在加载中的情况,而前者则可以通过回车键来刷新加载状态安装完成时重新运行npmrunstart,你会看到欢迎界面: ......
  • [LeetCode] 1535. Find the Winner of an Array Game
    Givenanintegerarrayarrofdistinctintegersandanintegerk.Agamewillbeplayedbetweenthefirsttwoelementsofthearray(i.e.arr[0]andarr[1]).Ineachroundofthegame,wecomparearr[0]witharr[1],thelargerintegerwinsandremainsat......
  • Could not find codec parameters for stream 0 (Video: h264, none)
    Couldnotfindcodecparametersforstream0(Video:h264,none)在使用视频处理工具或者播放器时,有时我们可能会遇到错误信息"Couldnotfindcodecparametersforstream0(Video:h264,none)"。这个错误提示说明在当前的环境中找不到视频流的编解码器参数,导致无法正确解......
  • 并查集学习笔记
    概念及其介绍并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。并查集的思想是用一个数组表示了整片森林(parent)树的根节点唯一标识了一个集合我们只要找到了某个元素的的树根就能确定它在哪个集合里。并查集构造方法publicclassUnion{intn;int......
  • union
    union   Takestwoormorepolygonsandreturnsacombinedpolygon.Iftheinputpolygonsarenotcontiguous,thisfunctionreturnsaMultiPolygonfeature.获取两个或多个多边形,并返回一个组合多边形。如果输入的多边形不是连续的,这个函数将......
  • shell find scp 命令
    一、背景有时我们需要把find找到的文件,scp到远程机器上。下面分享一下几个常见用法 二、解决方案2.1方案一查询某个文件下文件大小大于10k的文件:find/home/user/dir-size+10k查找大于4的文件,全部复制到另一目录:find/home/user/dir/-size+4k-execcp{}......
  • UNION和GROUP BY连用 导致的无法谓词推入问题
    问题概述在分析客户环境的一条SQL时,发现了无法做谓词推入的现象。造成视图中的大表访问比较低效。故此对案例做了进一步分析及测试。以确定问题原因。问题SQL:SELECTSUM("A2"."PREM")FROM((SELECT"A5"."AGENT_ID",SUM("A5"."PREM")"PREM"FROMQUERY_DES......
  • 并查集,路径压缩
    目录并查集并查集路径压缩并查集并查集:(union-findsets)是一种简单的用途广泛的集合.并查集是若干个不相交集合,能够实现较快的合并和判断元素所在集合的操作,应用很多,如其求无向图的连通分量个数、最小公共祖先、带限制的作业排序,还有最完美的应用:实现Kruskar算法求最小生成树。从......
  • Fail to find the dnn implementation node CudnnRNN
    tensorflow.python.framework.errors_impl.UnknownError:   Failtofindthednnimplementation.   [[{{nodeCudnnRNN}}]]   [[model/lstm/PartitionedCall]][Op:__inference_train_function_3343]Functioncallstack:train_function->train_function->tr......
  • F. Unique Occurrences(线段树分治+可撤销并查集)
    F.UniqueOccurrences假如我们删除所有权值为x的边,那么所有权值为x的边对答案的贡献就是\(\sumsz[u]*sz[v]\)sz表示两个联通块的大小,且(u,v)的边权为x我们可以用可撤销并查集来进行处理,简单来说就是将一条边的存在时间看作区间,然后挂到线段树上,然后遍历到每个叶子的时候进行......