一、并查集的应用:
并查集是一种树形数据结构
(1)用于简单地合并和查询上级关系
(2)用于判断无向图内的每个连通块的节点数量
(3)带权并查集
二、并查集一般模板:
(1)基础并查集:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int pre[N], n;
void init() {
for (int i = 1; i <= n; i++)
pre[i] = i;
}
int find(int x) {
if (pre[x] != x)
pre[x] = find(pre[x]);
return pre[x];
}
void join(int a, int b) {
int fa = find(a), fb = find(b);
if (fa != fb) {
pre[fa] = fb;
}
}
int main() {
cin >> n;
return 0;
}
(2)并查集维护无向图连通块:
对于size数组,只需要保证每个连通块的根节点的size有意义即可
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int pre[N], n;
int size[N];//多了一个size数组,用于维护连通块内的节点数
void init() {
for (int i = 1; i <= n; i++)
pre[i] = i;
}
int find(int x) {
if (pre[x] != x)
pre[x] = find(pre[x]);
return pre[x];
}
void join(int a, int b) {
int fa = find(a), fb = find(b);
if (fa != fb) {
pre[fa] = fb;
size[a] += size[b];
}
}
int main() {
cin >> n;
return 0;
}
放一道题目: AcWing 837. 连通块中点的数量 (已做笔记)
AcWing 4793. 危险程度(已做笔记)
三、带权并查集:
带权并查集是基于路径压缩优化的数据结构,与一般的并查集不同,带权并查集除了保存节点之间的链接关系之外,还有额外的一个数组保存每个节点到其父节点的权值,又因为存在路径压缩,所以调用find()函数(查找)后,父节点就变为根节点了,所以find()之后可认为记录权值的数组的含义是每个节点到根节点的权值
带权并查集的一些小技巧:
1.可以将求队列长度等转化为求每个节点到根结点的距离,然后用相关的权值数组来维护
2.看到拼接、前置、链接、上级等字眼可以考虑并查集
目前对带权并查集的理解还是有点乱,总结一下:
带权并查集本质就是并查集,该合并的还是要合并,只不过还要巧妙地设置一些权值,并且在合并的过程中更新,然后用这些权值表示集合中各点的对应关系
下面放两道题目: AcWing 240. 食物链(已笔记) AcWing 238. 银河英雄传说(好题)