• 【模板】并查集


    //洛谷P3367

    并查集算法也算是算法中的经典了,它可以用O(logn)的时间支持一张图中集合的合并与查询。

    这里,我们首先用一个数组fa[x]来表示以x为编号的祖先的编号(*每一个点的初始祖先为它自身)。

    然后就是并查集的重中之重:find()函数!!!

    int find(int x){
        if(x==fa[x]) return x;
        else return fa[x]=find(fa[x]);
    }

    find(x)就是查询点x 所在集合的祖先,并更新fa[x]。

    这里注意,如果没有fa[x]=find(fa[x]),而只是return find(fa[x])的话,操作久了,树就会退化成一个链,而失去其logn的时间复杂度,很容易T。

    然后,是实现集合之间的合并:merge()

    void merge(int x,int y){
        if(find(x)!=find(y)) 
            fa[find(x)]=fa[y];
    }

    这样就把x 所在集合的祖先接在y 所在的集合的祖先下面,其中fa[find(x)]=fa[y]也可写成fa[fa[x]]=fa[y]。

    最后就是并查集的查询操作:query()

    bool query(int x,int y){
        if(find(x)==find(y)) return true;
        else return false;    
    }

    如果x,y祖先相同,那么他们就在一个集合中,反之则不然。

    最后代码整合一下如下:

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #define maxn 10000 + 10
    using namespace std;
    int n,m,opr,v,u;
    int fa[maxn];
    int find(int x){
        if(x==fa[x]) return x;
        else return fa[x]=find(fa[x]);
    }
    void merge(int x,int y){
        if(find(x)!=find(y)) 
            fa[find(x)]=fa[y];
    }
    bool query(int x,int y){
        if(find(x)==find(y)) return true;
        else return false;    
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++) {
            scanf("%d%d%d",&opr,&u,&v);
            if(opr==1) merge(u,v);
            else if(query(u,v)) printf("Y
    "); 
                 else printf("N
    ");
        }
        return 0;
    }
  • 相关阅读:
    《统计学习方法》笔记十 隐马尔可夫模型
    《统计学习方法》笔记九 EM算法及其推广
    《统计学习方法》笔记八 提升方法
    《统计学习方法》笔记七(3) 支持向量机——非线性支持向量机
    拜拜~~~
    拓扑排序+DP CF721C Journey
    数学 CF1068B LCM
    扩展欧拉定理【洛谷P4139】 上帝与集合的正确用法
    浅谈扩展欧拉定理
    数论 CF230B T-primes
  • 原文地址:https://www.cnblogs.com/XjzLing/p/7943363.html
Copyright © 2020-2023  润新知