并查集详解与应用
并查集是一种树形的数据结构,顾名思义,它用于处理一些不交集的 合并 及 查询 问题。 它支持两种操作:查询、合并。查询用于查找元素在哪个子集中,合并用于将两个子集合并成一个。
这是一个什么样的结构体?一个 int[] fa
即可。每个结点都只有一个父节点, fa[3] == 1
,表示的是 3 号结点的父节点为 1,特别的,祖父结点的父节点为本身。
初始化
首先是初始化,每个结点的父节点设置为自己。
1 | public void init(int n) { |
查询
查询操作是查找一个结点的祖宗结点的过程,简单递归即可。
1 | public void find(int node) { |
路径压缩
我们在查询之后,得到了某个结点的祖宗结点。如果不做优化,下次查询该结点可能还需要很多步,纯属浪费,我们可以直接将该结点,提到祖宗结点的下一层,下次查询非常快。
啰嗦写法,但易懂。
1 | public void find(int node) { |
简单写法。
1 | public void find(int node) { |
合并
1 | public void union(int x, int y) { |
应用
哪些问题可以使用并查集来解决?
- 查找元素属于哪个集合
- 判断两个元素是否在同一个集合
- 计算集合的个数,森林中子森林的个数。
心得
并查集一般都是使用 int []
来存储数据,但一些情况下题目提供的是字符串或者其它对象,我们需要将这些元素映射到数组 int []
中,同时使用一个 Map
来存储原字符串和 int []
中下标的对应关系,即存下标。可以看例题 399 题,「除法求值」。
另外还有一些题目,不再是简单的并查集,并查集中除了 fa[]
数组,还需要维护一些其他数据,这就r是带权并查集,还是可以看「除法求值」这一题。