并查集

这篇具有很好参考价值的文章主要介绍了并查集。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

并查集

并查集

并查集

并查集是用来判断两个元素是否属于同一个集合

即判断他们的根节点是否相同

一.代码与思想

1. 初始化

#define maxn 100
int parent[maxn];

void init(int n)
{ 
	for(int i = 0;i <n;i ++)
	{
		parent[i] = i;//存放每个节点的节点(或者是双亲节点) 
	}
}

2.查询根节点

int find(int x)
{
	if(parent[x] == x)
		return x;
	else
		return find(parent[x]);
} 

3.合并

//合并,把j合并到i中去,就是把j的双亲节点设为i
void merge(int i,int j)
{
	parent[find[j]] = find(i); 
	//此时要合并节点i与j,并不能将他们直接合并
	//需要先查找他们各自的老大(根节点)是谁
	//将j的根节点合并到i的根节点下方 
} 

二.路径压缩

集合变为一个长长的链时,查找变得十分麻烦,此时我们需要路径压缩
即每个人的直接根节点就是最上面的根节点
我们判断两个元素是否是同一个集合,看的是他们的 根节点 是否相同
那么我们可以直接把 每个元素的父节点 改为这个集合的代表元素,即根节点
所以我们只要在查找的过程中,把沿途的每个 双亲节点 都设为根节点即可
int find(int x) 
{
	if(parent[x] == x)
	{
		return x;
	}
	else
	{
		parent[x] = find(parent[x]);
		return parent[x]; 
	}
}

或者可以简化为下面的一行版文章来源地址https://www.toymoban.com/news/detail-709802.html

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

三. 按秩合并

并查集经过路径压缩后,并不是只有两层的一棵树

最终的结构仍然可能很复杂

1. 思想

为了使树变得更加简洁,我们应该把简单的树往复杂的树上合并

即:把 深度小 的树合并到 深度大 的树中

这样每个元素到根节点的 距离变化的元素个数 最小

2. 按秩合并的做法

1)我们用rank[]数组来记录每个根节点对应的树的深度,如果不是根节点,那么rank[i]表示当前节点作为根节点时的子树的深度

2) 一开始,把所有rank[] = 1,即自己就为一棵树,且深度为1

3)合并的时候,比较两个根节点,把rank较小者合并到较大者中去

2.1 初始化

void init (int t)
{
	for(int i = 0;i <n;i ++)
	{
		parent[i] = i;
		rank[i] = 1;
	}
 } 

2.2合并

void merge(int i,int j)
{
	int x = find(i),y = find(j);
	if(rank[x] < rank[y])
		parent[x] = y;
	//如果以x作为根节点的子树深度小于以y作为节点的子树的深度
	//将x合并到y中
	else
		parent[y] = x;
		
	if(rank[x] == rank[y] && x != y)
		rank[x] ++;
	//如果深度相同且根节点不同,以x为节点的子树的深度+1 
	//即将y合并到x下 
}

三.并查集模版

<洛谷 P3367 【模板】并查集 >

#include<bits/stdc++.h>
using namespace std;
int a[200005],b[200005];
int n,m;
int parent[200005],rank[20005];

void init(int num)
{
	for(int i = 0;i < num; i++)
	{
		parent[i] = i;
		rank[i] = 1;
	}
	
}

int find(int x)
{
	if(parent[x] == x)
		return x;
	else
	{
		parent[x] = find(parent[x]);
		return parent[x];
	}
}

void merge(int x,int y)
{
	int rx = find(x);
	int ry = find(y);
	
	if(rx != ry)
	{
		if(rank[rx] < rank[ry])
			swap(rx,ry);
		parent[ry] = rx;
		if(rank[rx] == rank[ry])
			rank[rx] ++;
	}
}![](https://img2023.cnblogs.com/blog/3275618/202309/3275618-20230910161641407-554815287.png)


int main()
{
	cin>>n>>m;
	init(n);
	for(int i = 1; i <= m; i++)
	{
		int x;
		cin>>x>>a[i]>>b[i];
		if(x == 1)
			merge(a[i],b[i]);
		if(x == 2)
		{
			if(find(a[i]) == find(b[i]))
				cout<<'Y'<<endl;
			else
				cout<<'N'<<endl;
		}
	}
	return 0;
}
 

到了这里,关于并查集的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图论:并查集的合并、判断和求节点

     所谓并查集就是可以画图理解 假如说我们想要构建一个树(也是图),要求1-2,2-4,1-3 在构另一个树,要求5-6,6-7,5-8 1是2的头结点,2是4的头结点,以此类推 下面要求去将5连接到1上,就是我下面要讲的,其实上面的子节点的连接也是如此的。 简单并查集例题: 一共有 n 个数

    2024年01月18日
    浏览(35)
  • 并查集(种类并查集,带权并查集)

    链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网   动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形。A吃B,B吃C,C吃A。 现有N个动物,以1-N编号。每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种。 有人用两种说法对这N个动物所

    2024年02月11日
    浏览(38)
  • java 判断两个List是否包含 判断两个list相等

    java 判断两个List是否包含 判断两个list相等 https://blog.51cto.com/u_12855/7333853 1、直接使用equals()比较 众所周知,两个列表具有完全相同的元素并且具有完全相同的顺序时,它们是相等的。因此, 如果我们业务要求两个list顺序一致,可以使用equals()方法进行相等性检查: 即使

    2024年02月04日
    浏览(61)
  • 判断两个数组是否相等

    在判断两个数组是否相等之前,我们应该弄清楚数组怎样才算相等,官方给的解释是这样的: Returns true if the two specified arrays of ints are equal to one another. Two arrays are considered equal if both arrays contain the same number of elements, and all corresponding pairs of elements in the two arrays are equal. In other

    2024年02月15日
    浏览(58)
  • selenium元素操作--判断元素是否可用、可选中、是否可见

    Ctrl + 左键可以调出某方法的使用 is_selected() 方法 返回一个布尔值,若可见则返回: True 。若不可见则返回: False 。 is_displayed() 方法返回一个布尔值,若可见则返回: True 。若不可见则返回: False 。 is_enabled() 方法返回一个布尔值,若可点击返回: True 。若不可点击则返回:

    2024年04月13日
    浏览(88)
  • 判断两个vector数组是否相等

    判断两个vector数组是否相等是可以直接使用==或者!=的 因为vector内部都进行了相关运算符的重载,还可以进行比较大小 下面这道简单搜索题就用到了这个性质,浅看一下吧 【问题描述】给定一个n个整数的集合X={x1,x2,…xn}(X中可能包含重复元素)和整数y,找出和等于y的X的子集

    2024年02月12日
    浏览(62)
  • 判断两个时间段是否有交集

    前言:项目中遇到了类似会议室预约的时间段被占用,预约车辆时间段被占用等。 start:预约开始时间。 end:预约结束时间。 必备条件:start = end 思考🤔: 怎么判断是否被占用呢? 预约的时间,与目标数据库中任意一条的存在交集,则可以视为占用。 有交集的情况有那几

    2024年02月03日
    浏览(64)
  • Js如何判断两个数组是否相等?

    日常开发,时不时会遇到需要判定2个数组是否相等的情况,需要实现考虑的场景有: 先判断长度,长度不等必然不等 元素位置 其他情况考虑 \\\'1\\\' 和 1 (Object的key是字符串, Map的key没有限制) NaN null 和 undefined 数组自带的方法,比较适合的有: every、some、filter、findIndex 。 这种

    2024年02月22日
    浏览(64)
  • 小程序进入webView进行微信公众号授权获取用户openId,用来判断用户是否关注与当前小程序关联的公众号

    文档:网页授权 | 微信开放文档   4.1 appid:为公众号的appid,前期可以去申请测试公众号,地址:微信公众平台 4.2 redirect_uri:由后端提供,在这里面进行授权 4.3 response_type:授权获取到的code值,这里默认为code,后端会根据这个code来获取openId 4.4 scope:有两种类型,snsapi_

    2024年02月04日
    浏览(70)
  • 如何判断两个随机变量是否独立,同分布

    独立两个判断条件 1,设(x,y)的密度函数为f(x,y),其定义域是矩形区域。联合密度函数的区域必须为矩形区域,这很重要。可以证明一波,若x的范围为(0,1),y的范围为(3,5)如果他们相互独立,那么组成的联合密度函数,每一个x,都可以对应所有的y,所以组成的范围为矩

    2024年02月11日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包