zoukankan      html  css  js  c++  java
  • Union-Find

    一、概念

    一个集合中的元素,仅有的关系就是同属于这个集合,并查集就是用来维护若干集合的一种数据结构。
    并查集有两个基本操作:

    1. 并:合并两集合;
    2. 查:查询两个元素是否属于同一个集合。

    为了方便地实现合并以及查找操作,我们在一个集合中规定唯一一个根结点,并将这个根结点作为该集合的标志。
    开始时所有元素都是一个独立的集合:

    int parent[MAXN];
    for (int i = 0; i < n + 1; i++) { // 下标从1开始
    	parent[i] = i;    //i元素的父结点初始化为自己,也可以初始化为-1
    }
    

    二、合并与查找

    • Find
      查找的同时可以通过路径压缩来将均摊复杂度降低为(O(1))。查找某个结点时,将其经过的全部结点直接连到父结点,这样下次查询时次数就会减少。
    • Union
      合并时可以遵循按秩合并原则,将秩小的树合并到秩大的树,降低路径压缩时的开销。
      将两个不同的集合合并为一个集合,只要将其中一个集合的根结点的parent指向另一个集合的根结点即可。
      对于属于同一个集合的两个元素的合并没有意义,所以我们一般只对两个不同的集合进行合并。

    虽然这种树结构的并查集可以将均摊复杂度变为(O(1)),但如果涉及到删除元素、计算每个集合元素个数等操作时,实现会有些复杂;
    最原始的并查集虽然复杂度稍差,但是可以完成的功能比较多。原始并查集实现

    class unionFind {
    private:
        vector<int> parents_;
        vector<int> ranks_;
    public:
        unionFind(int n) {
            for(int i = 0;i <= n;++i) {
                parents_.emplace_back(i);
                ranks_.emplace_back(0);
            }
        }
    
        // get the root of x
        int Find(int x) {
            // path compression
            if(x != parents_[x]) {
                parents_[x] = Find(parents_[x]);
            }
            return parents_[x];
        }
    
        // merge set u and v
        // false -> u and v are already in one set
        bool Union(int u, int v) {
            int rootu = Find(u);
            int rootv = Find(v);
            if(rootu == rootv) 
                return false;
    
            // merge low rank to high rank
            if(ranks_[rootu] < ranks_[rootv]) {
                parents_[rootu] = rootv;
            }
            else if(ranks_[rootv] < ranks_[rootu]) {
                parents_[rootv] = rootu;
            }
            else {
                parents_[rootu] = rootv;
                ++ranks_[rootv];
            }
    
            return true;
        }
    };
    

    一道例题:亲戚
    不做路径压缩可以求最小环长

    三、种类并查集(TODO)

    普通并查集的特点就是只有一个集合,比如上述例题只有亲戚一个集合。如果涉及到多个集合,就需要种类并查集。
    假如有n个集合,常用的手法就是开一个n倍大小的并查集。
    食物链
    团伙

  • 相关阅读:
    RSA解密时BadPaddingException解决方法
    CAP定理的理解
    服务降级、熔断、隔离
    javascript原型 原型链
    Redis基础数据类型及应用场景
    log4j
    个人免签支付
    Spring Security Oauth2 认证
    elementUI的栅格布局
    用 Vue+ElementUI 搭建后台管理极简模板
  • 原文地址:https://www.cnblogs.com/EIMadrigal/p/11729710.html
Copyright © 2011-2022 走看看