并查集概述

并查集(Union-Find)

概述

并查集是一种高效的数据结构,以多棵树的形式存储,每棵树有一个被打上标记的根节点

主要用途:

  • 合并两个集合
  • 查询元素所属的集合

常见题型:

  • 朴素并查集
  • 带权并查集
  • 维护size并查集

结构

并查集通常使用三个数组实现:

  • p[] (parent)数组:记录每个元素的父节点。
  • d[] (distance)数组:记录每个元素到父节点距离
  • size[]数组:记录每个并查集的大小

ps:虽然并查集在逻辑结构上是一棵棵在同一集合的树,但是存储结构仍可以用普通的数组实现

操作

1.建立

初始化并查集

并查集根节点root:的标记方式p[root] = root

表示根节点的父节点就是自己

void init()
{
	// 一开始每个节点各自为营
	for (int i = 1; i <= n; i ++ )
		p[i] = i;
} 

2.查找

查找元素 x 所在集合的根节点:

优化:利用递归在查找的时候就直接把每个节点的父节点压缩向了祖宗节点,此时距离d也更新为了到父节点(祖宗节点)的距离

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    // p[x]效果为找x的祖宗节点
    // 这里调用p[x] = find(p[x])直接让x的父节点指向了p[x]的祖宗节点
    // 经过层层递归会最终指向整棵树的根节点
    int root = find(p[x]); 
    // 先要存root是因为只有先跑find()才能让d[p[x]]变为p[x]到祖宗节点的距离
    d[x] += d[p[x]];
    return root;
}

3.合并

合并两棵树:

void merge(int x, int y)
{
	// 找出两棵树的根节点
	int px = find(x), py = find(y);
	
	// 根节点不同才需要合并
	if (px != py) 
    {
		p[px] = py;
        size[py] += size[px];
        // 可能还需要对d[px]进行操作,具体情形依题目而定
	}
}

至此,并查集的基本操作均已介绍完毕,操作简洁作用大,用处这么大的数据结构上哪里找呀~

来几道例题尝试尝试~

例题

朴素并查集

洛谷 P3367 【模板】并查集


维护size的并查集

洛谷P1455 搭配购买


维护到祖宗节点距离的并查集(带权并查集)
洛谷P1196 银河英雄传说

洛谷P2024食物链

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值