并查集离散化

以下是一个并查集离散化的模板(我个人觉得相对于开数组方式来说,当然这种数组转哈希的技巧在线段树离散化里面同样适用,可能是我孤陋寡闻了),以前背的并查集板子是开数组并且使用负数来作为连通分量的秩的,但是遇到一些键不是整型的题目,还需要自己做键类型之间的映射比较麻烦,以及一些取值范围很大的键,数组根本开不到那个范围。其实把数组替换为哈希表就好了,其他的基本没什么改动的地方,麻烦的就是使用一个根之前必须先手动插入,给我的感觉大概是 懒汉式饿汉式 的区别:

  • 饿汉式:开数组,数组每个元素代表了一个节点,虽然后续大量的节点可能根本没有参与合并的过程,就是像饿汉式一样不管有没有用到一开始就创建
  • 懒汉式:哈希表,存在合并行为的根再执行创建
template <typename Tkey>
class DisjointSet {
private:
    unordered_map<Tkey, Tkey> G;
    unordered_map<Tkey,  int> R;

public:
    void insert(Tkey x) {
        if (G.count(x)) return;
        G[x] = x;
        R[x] = 1;
    }

    Tkey find(Tkey x) {
        if (!G.count(x)) return x;
        if (R[x] > 0) return x;

        return G[x] = find(G[x]);
    }

    void merge(Tkey x, Tkey y) {
        if (!G.count(x) || !G.count(y)) return;

        Tkey rx = find(x);
        Tkey ry = find(y);
        if (rx == ry) return;

        if (R[rx] > R[ry]) {
            R[rx] += R[ry];
            R[ry] = 0; // not a root anymore
            G[ry] = rx;
        } else {
            R[ry] += R[rx];
            R[rx] = 0; // not a root anymore
            G[rx] = ry;
        }
    }

    int rank(Tkey x) {
        // 所在连通分量的顶点数量
        if (!G.count(x)) return 1;
        return R[find(x)];
    }
};

G G G 指的是 graph 图本身, R R R 指的是图中每个顶点所在连通分量的秩,是用于按秩合并的时候使用的,路径压缩总是会被执行,任何的合并都将导致查询先发生,因而一棵连通分量树的高度要么是 1 要么是 2,合并以后树的高度不会超过 3 。

每次合并的时候,被成为子节点的节点将失去根节点标志性的非零秩,我们总是把一棵连通分量树的所含顶点数量(秩)存放在根节点,非根节点的秩总是 0 ,这样便于我们区分哪些节点是根节点,作为路径压缩时候停止递归的条件。

一个使用示例可以看我的另一篇博客 Leetcode 399. 除法求值 【离散化并查集】

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值