前言
好久不见,作者连续两个星期准备比赛,终于比完了,接着来更新c++的内容
什么是并查集
并查集是一种树型的数据结构,用于处理不相交的合并及查询问题。
并查集的思想是用一个数组表示了整片森林(parent),树的结点唯一标识了一个集合,我们只要找到的某个元素的树根,就能确定它在哪个集合里。
1.并查集要一般处理的问题
(1)合并:将若干个点合并到一个或多个集合(构成一棵树或多棵树),将多个集合合并(多棵树合并为一棵树);
(2)查询:询问某2个点是否在同一个集合里(查询);
(3)其他:计算共有几个集合(几棵树);
2.并查集的实现方法
(1)举例说明
假设有如下 8 个点:1 2 3 4 5 6 7 8,假设如下两两的结点在一个集合中,通过并查集构建过程的模拟来看最终有几个集合,并理解并查集的构建过程和查询过程。
两辆在一个集合中的结点有:
1 3
1 2
5 4
2 4
6 8
8 7
(2)数据结构的实现
实际操作时,我们会使用一个点来代表整个集合,即一个元素的根结点(可以理解为父亲)。
实现方法
我们建立一个数组fa[]表示一个并查集,fa[i]表示 i 的父节点。
(1)初始化:每一个点都是一个集合,因此自己的父节点就是自己 fa[i]=i
(2)查询:每一个节点不断寻找自己的父节点,若此时自己的父节点就是自己,那么该点为集合的根结点,返回该点。
(3)合并:合并两个集合只需要合并两个集合的根结点,即 fa[RootA]=Rootb,其中RootA,RootB 是两个元素的根结点。
(4)路径压缩:
大多数情况下,在查询过程中只关心根结点是什么,并不关心这棵树的形态。因此我们可以在查询操作的时候将访问过的每个点都指向树根,这样的方法叫做路径压缩。
初始化模板:
for(int i=1;i<=n;i++) f[i]=i;
//基本查询模板:求x的根
int find(int x){
return f[x]==x?x:find(f[x]);
}
//路径压缩查询模板:
f[x]==x?x:find(f[x]);
//合并模板:先判断x和y是否同在一个集合
//集合合并
void merge(int x,int y){
int fx = find(x);
int fy = find(y);
if(fx!=fy) f[fx]=fy;
}