并查集

并查集是什么

并查集是一种树形的数据结构,顾名思义,它用于处理一些不交集的 合并 及 查询 问题。 它支持两种操作:

  1. 查找(Find):确定某个元素处于哪个子集;
  2. 合并(Union):将两个子集合并成一个集合。
    dsu1.png
    简单来说就是用树的形式来维护集合,支持合并和查询。

基本原理

每个集合用一棵树来表示,树根编号就是集合编号,每个节点用p[x]储存其父节点。

几个重要的问题

  1. 如何判断是不是树根?
    判断x是否==p[x].
  2. 如何求x的集合编号?
    while(p[x]!=x) x=p[x];
  3. 如何合并集合
    px是x的集合编号,py是y的集合编号,只要让p[px]=py;

优化

路径压缩:搜一次顺便将路上的点连接到root节点。

核心操作

find函数(找到根节点顺便路径压缩)。

int find(int x){
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}

并查集的变形

维护数量的并查集 acwing 837.连通块中点的数量
维护距离的并查集 POJ 1182 食物链(带权并查集)

带权并查集的 find 函数

int find(int x){
    if(p[x] != x){
        int t = p[x];
        p[x] = find(p[x]);
        d[x] += d[t];
    }
    
    return p[x];
}

先把 p[x] 暂存是因为路径压缩完之后 p[x] 就变成 root 了,而不是现在的父节点。

带权并查集 Union

根据题目变化而调整,以下是一个例子

p[py] = px;
d[py] = d[x] - d[y] + z;

附上 CSDN 看到的一篇关于带权并查集的还不错的讲解。
https://blog.csdn.net/yjr3426619/article/details/82315133

posted @ 2021-05-09 10:17  今天AC了吗  阅读(72)  评论(0)    收藏  举报