• 并查集的初步学习


    用一句话描述一下并查集:并查集是用树来表示集合,他把每一个连通分量看做一个集合,其中包含了连通分量中的所有点,其中一个连通分量中的点都有共同的父亲结点。
    具体的构造:
    1. 初始化,每个点的父节点指向自己。
    2. 如果两个点有边,那么就在一个连通分量中,所以指向同一个父节点。
    3. 最后所有点都会指向各自的父节点,父节点相同的在一个连通分量中。
    基本代码就一行:

    int findfa(int x){return x==fa[x]?x:fa[x]=findfa(fa[x]);}

    上几道入门的题目:
    hdu 1213 求连通分量的个数
    hdu 1232 求最少需要几条边可以使所有点都连通。也是求出连通分量的个数-1即是答案

    #include<cstdio>
    #include<cstring>
    const int N=1001;
    int fa[N];
    int findfa(int x){return x==fa[x]?x:fa[x]=findfa(fa[x]);}
    //int findfa(int x)
    //{
    //    while(x!=fa[x])x=fa[x]; //循环也可以
    //    return x;
    //}
    bool vis[N];
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m)&&n){
            for(int i=1;i<=n;i++)fa[i]=i;
            int u,v;
            for(int i=0;i<m;i++){
                scanf("%d%d",&u,&v);
                int x=findfa(u),y=findfa(v);
                if(x!=y)fa[x]=y;
            }
            int ans=0;
            memset(vis,0,sizeof(vis));
            for(int i=1;i<=n;i++){
                if(!vis[findfa(i)])ans++;
                vis[findfa(i)]=1;
            }
            printf("%d
    ",ans-1);
        }
        return 0;
    }

    hdu 1272
    题意:
    给出一些边,要求这些边连成一个连通图,并且无环,就是构成一棵生成树
    分析:
    用并查集做,如果两点在连边的时候,他们的父节点相同,说明他两已经在一个连通图了,而现在又连上一条边,构成环。

    //hdu 1272
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=100002;
    int fa[N];
    bool vis[N];
    int findfa(int x){return x==fa[x]?x:fa[x]=findfa(fa[x]);}
    int main()
    {
        int u,v;
        while(~scanf("%d%d",&u,&v)){
            if(u==-1&&v==-1)break;
            if(u==0&&v==0){ //需要注意这里,输出Yes
                printf("Yes
    ");continue;
            }
            memset(vis,0,sizeof(vis));
            for(int i=0;i<N;i++)fa[i]=i;
            int x=findfa(u),y=findfa(v);
            fa[x]=y;
            vis[u]=vis[v]=1;
            int t=u;
            bool flag=1;
            while(scanf("%d%d",&u,&v)&&(u||v)){
                x=findfa(u),y=findfa(v);
                if(x==y)flag=false; //如果两个点的父结点相同,说明有环
                fa[x]=y;
                vis[u]=vis[v]=1;
            }
            if(!flag){
                printf("No
    ");continue;
            }
            x=findfa(t);
            for(int i=1;i<N;i++){
                if(vis[i]&&findfa(i)!=x){
                    flag=false;break;
                }
            }
            if(flag)printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }

    题目:hdu 1198
    题意:
    给出一些图片,图片上水管可以相接的就可以连通,求连通块数。
    分析:
    可以现根据图片是否可以连通,建一个图,然后再用并查集就好。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=55;
    int fa[N*N];
    int findfa(int x){return x==fa[x]?x:fa[x]=findfa(fa[x]);}
    int a[][4]={
        {1,0,0,1},{1,1,0,0},{0,0,1,1},{0,1,1,0},{1,0,1,0},
        {0,1,0,1},{1,1,0,1},{1,0,1,1},{0,1,1,1},{1,1,1,0},{1,1,1,1}};
    char g[N][N];
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m)){
            if(n<0||m<0)break;
            for(int i=0;i<n;i++)scanf("%s",g[i]);
            for(int i=0;i<n*m;i++)fa[i]=i;
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    int x=findfa(i*m+j),y;
                    if(j+1<m&&a[g[i][j]-'A'][1]&&a[g[i][j+1]-'A'][3]){
                        y=findfa(i*m+j+1);
                        if(x!=y)fa[y]=x;
                    }
                     if(i+1<n&&a[g[i][j]-'A'][2]&&a[g[i+1][j]-'A'][0]){
                        y=findfa((i+1)*m+j);
                        if(x!=y)fa[y]=x;
                    }
                }
            }
            int ans=0;
            for(int i=0;i<n*m;i++)
                if(findfa(i)==i)ans++;
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    WEB开发者必备的7个JavaScript函数
    json分别算出元素的个数和最多的元素
    jquery 对 Json 的各种遍历
    判断图片是否加载完成
    obj转换成数组
    用JavaScript获取页面上被选中的文字的技巧
    PAT 1088 三人行(20 分)(暴力破解+流程分析)
    PAT 1087 有多少不同的值(20)(STL-set代码)
    PAT 1086 就不告诉你(15 )(代码)
    PAT 1087 有多少不同的值(20)(STL—set)
  • 原文地址:https://www.cnblogs.com/01world/p/5651251.html
Copyright © 2020-2023  润新知