并查集的基本使用

并查集用于快速的分类和查找,处理一些不相交集合的合并与查询
基本的操作:
1. 初始化,把每个值对应的集合都设为自己
2. 合并,把一个集合合并到另一个上
3. 查询,本博客采用路径压缩算法实现查询的操作,查找元素在集合中对应的集合位数

/* 
基本的操作:
1.初始化,把每个值对应的集合都设为自己
2.合并,把一个集合合并到另一个上
3.查询,本博客采用路径压缩算法实现查询的操作,查找元素在集合中对应的集合位数
*/

#include <iostream>
using namespace std;
#define max 1000000

int parent[max];    //定义一个parent数组,parent[i]表示i元素所对应的集合为parent[i]

int find( int p )   //路径压缩的find算法
{
	if( parent[p] != p ) return parent[p] = find( parent[p] );    //如果根不是自己,那么就递归调用find函数找到根并连接 
	return parent[p];      		//否则直接返回
}

int main()
{
	int n;
	cin >> n; 
	for (int i = 1; i <= n; i++ )
	{
		parent[i] = i;    //初始化
	}
	int m;
	cin >> m;
	for (int i = 1; i <= m; i++)
	{
		int x,y;
		cin >> x >> y;
		int rootx = find(x);
		int rooty = find(y);
		parent[rootx] = rooty;    //由于进行了路径压缩,所以直接随意的把一个集合接到另一个上
	}
    return 0;
}

复杂度:N次合并M查找的时间复杂度为O(M Alpha(N)),这里的Alpha(n)可以视为不超过4的数,所以可以视并查集的操作为有系数的线性时间。
并查集的启发式合并:
由于路径压缩改变了树的结构,所以在可撤销并查集和可持久化并查集时就不大好用了。所以采用启发式合并有时就会有优势。
并查集的启发式合并就是在两个集合合并的时候,将siz小的连向siz大的。复杂度为O(nlogn)。
主要的复杂度在于找到根节点。我们考虑一次合并,将siz小的连向大的,这时候只有siz小的那棵子树在以后的查询中多跑一次(因为祖先节点多了一个),我们考虑一个节点最深在哪里,那就是不断的作为siz小的那一部分合并,那这时候每次深度加1,总大小至少翻倍,所以最深log层。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值