数据结构:并查集
并查集是一种 树型数据结构,主要用来处理 集合的合并与查询 问题。
它的核心功能有两个:
Find(查询):查询某个元素属于哪个集合(找到集合的代表/根)。
Union(合并):将两个集合合并成一个集合。
每个集合用一棵树表示,树根是集合的代表。
每个元素存一个 父亲指针(parent[i]),指向它的父节点。
如果 parent[i] == i,说明它是根节点。
解决简单并查集问题的步骤:
1.声明数据集合,并初始化
int f[1005];
for(int i=1;i<=n;i++)
{f[i]=i;
}
2.查找是否在同一个集合(通过查是否是同一个根来判断)
int a;
int b;
int la=find(a);
int lb=find(b);
int find(int x)
{if(x==f[x]){return x;}else{f[x]=find(f[x]);return f[x];}}
3.判断是否在同一个集合中,如果没有添加进去,添加的方法就是将其中一个的根的根设置成另外一个
if(la==lb)
{说明在同一个集合中
}
else
{f[la]=lb;
}
查找的时候可以进行路径压缩
为啥会有路径压缩呢,因为在查找一个数据的根是谁的过程中,会遇到其他根与之相同的数据,它们的根是相同的,我们没有必要重复查询,在查询一个的过程中,把其他数据的根也改为总的根
int find(int x) {if (f[x] != x)f[x] = find(f[x]); // 递归时顺便把父亲指针直接指向根return f[x];
}
使用场景:
判断两个元素是否属于同一个集合(连通性问题)。
网络连通、朋友圈、最小生成树(Kruskal 算法)。
图论里常见的连通分量问题。
传统的并查集一般不会出题,
一种是其他算法和并查集结合
并查集 + 其他算法结合
这是最常见的考点。常见搭配有:
Kruskal 最小生成树
用并查集判断加入一条边后是否会产生环。
网络连通/岛屿数量
DFS/BFS 可以做,但也可以用并查集维护连通块数。
动态连通性问题
比如给你一堆操作(合并、查询是否在同一集合),并查集比 DFS/BFS 高效。
另一种是出种类并查集,一般是两个种类
维护一些对立关系,比如敌人的敌人是朋友时,正常的并查集就很难满足我们的需求这时种类并查集(扩展域并查集)就诞生了。
三个种类一般遇不到。