zoukankan      html  css  js  c++  java
  • 并查集2个优化——按秩合并和路径压缩

    并查集有两个优化。

    一、按秩合并

    描述:就是在对两个不同子集连接时,按照rank来连,也就是rank低的连在rank高的下面。rank高的做父亲节点。

    作用,这样类似维护了一棵树,树是rank高的在上。

     

    // 初始化n个元素
    void init(int n)
    {
        for(int i=0;i<n;i++)
        {
            parent[i]=i;
            rank[i]=0;   // 初始树的高度为0
        }
    }
    
    
    // 合并x和y所属的集合
    void unite(int x,int y)
    {
        x=find(x);
        y=find(y);
        if(x==y) return ;
        if(rank[x]<rank[y])
            parent[x]=y;  // 合并是从rank小的向rank大的连边
        else
        {
            parent[y]=x;
            if(rank[x]==rank[y]) rank[x]++;
        }
    }

    二、路径压缩

    描述:假如fa数组已经嵌套了N层,那么传统的做法去找祖先要做N次,当N很大时,这种做法很没效率。

    这是朴素查找的代码,适合数据量不大的情况

    int findx(int x)
    {
        int r=x;
       while(parent[r] !=r)
            r=parent[r];
       return r;
    }

        下面是采用递归路径压缩的方法查找元素,但是,递归压缩路径可能会造成溢出栈会发生RE

    int find(int x)       //查找x元素所在的集合,回溯时压缩路径
    {
        if (x != parent[x])
        {
            parent[x] = find(parent[x]);     //回溯时的压缩路径
        }         //从x结点搜索到祖先结点所经过的结点都指向该祖先结点
        return parent[x];
    }

     

    下面我们说一下非递归方式进行的路径压缩

    int find(int x)
    {
        int k, j, r;
        r = x;
        while(r != parent[r])     //查找跟节点
            r = parent[r];      //找到跟节点,用r记录下
        k = x;        
        while(k != r)             //非递归路径压缩操作
        {
            j = parent[k];         //用j暂存parent[k]的父节点
            parent[k] = r;        //parent[x]指向跟节点
            k = j;                    //k移到父节点
        }
        return r;         //返回根节点的值            
    }
  • 相关阅读:
    1523. K-inversions URAL 求k逆序对,,,,DP加树状数组
    Football 概率DP poj3071
    Collecting Bugs poj2096 概率DP
    E. Exposition
    Subsequence
    D. How many trees? DP
    hdu 1542 线段树 求矩形并
    Huge Mission
    2013 ACM/ICPC Asia Regional Chengdu Online hdu4731 Minimum palindrome
    008 jackson的一些使用记录
  • 原文地址:https://www.cnblogs.com/oiercc/p/7210136.html
Copyright © 2011-2022 走看看