zoukankan      html  css  js  c++  java
  • 并查集及其优化

    总结一下并查集吧。
    学了好多次结果都没记住。
    啊~~~~~~


    下面介绍一个我比较看得过去的并查集入门介绍

    下面是他给出的一个代码模板

    #include <iostream>
    using namespace std;
    const int N = 10010;
    
    int f[N];
    int high[N]; // 保存每个朋友圈的高度,初始时都是 0 
    
    /*
     * 将表示朋友圈的数组初始化,即将所有人的“朋友祖先”都设置为自己的 id ,
     * 于是就有了 n 个不同的朋友圈 
     */
    void init(int n)
    {
        for(int i = 1; i <= n; i++)
        {
            f[i] = i;
        }
    }
    
    // 得到 id 为 v 的人的“朋友祖先”的 id 
    int getFriend(int v)
    {  
        if(f[v] == v)
        {
            return v;
        }
        /*
         * 如果发现“朋友祖先”不是自己,那么他肯定被合并到别的朋友圈里面去了,
         * 那么继续调用这个函数来找这个朋友圈里面的“朋友祖先”,
         * 并且在这个过程中将找到的人都设置为同一个“朋友祖先”(因为都在同一个朋友圈里面) 
         */
        return f[v] = getFriend(f[v]);
    }
    
    /**
     * 将两个人所在的两个朋友圈合并为一个朋友圈 
     * 这里通过两个朋友圈的高度来决定合并方式 
     */
    void merge(int a, int b)
    {
        int t1 = getFriend(a); // 得到左边的人的“朋友祖先” 
        int t2 = getFriend(b); // 得到右边的人的“朋友祖先” 
        // 两个人的“朋友祖先”不一样,合并两个朋友圈 
        if(t1 != t2) {  
            // 如果左边的朋友圈的高度大于右边的朋友圈的高度,
            // 那么将右边的朋友圈合并到左边的朋友圈中 
            if (high[t1] > high[t2])
            {
                f[t2] = t1;
            // 否则就把左边的朋友圈合并到右边的朋友圈中 
            }
            else
            {
                f[t1] = t2;
                // 如果当前两个朋友圈的高度相等,那么合并之后的朋友圈高度要加1
                if (high[t1] == high[t2])
                {
                    high[t2]++;
                }
            }
        }
    }
    
    int main()
    {
        int n, m, k;
        cin >> n >> m >> k;
        int x, y;
        init(n);
    
        for(int i = 0; i < m; i++)
        {
            cin >> x >> y;
            merge(x, y);
        }
    
        /*
         * 输出合并之后的数组情况
         */
        for(int i = 1; i <= n; i++)
        {
            if(i != 1)
            {
                cout << " ";
            }
            cout << f[i];
        }
        cout << endl;
    
        for(int i = 0; i < k; i++)
        {
            cin >> x >> y;
            // 如果两个人的“朋友祖先”不相同,证明他们不在同一个朋友圈内,也就不是朋友
            if(getFriend(x) != getFriend(y))
            {
                cout << "no" << endl; 
            }
            else
            {
                cout << "yes" << endl;
            }
        }
        return 0;
    } 
    

    上面的代码是针对特定题目的,而且注释巨多。
    下面我总结一个比较简洁的代码模板吧,
    我也借机熟悉一下代码,嘿嘿~

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 10010;
    
    int f[maxn];//每个节点的父节点
    int high[maxn];//每个节点下属节点的高度(注意是高度不是个数)
    
    
    void Init()//初始化函数
    {
        memset(high,0,sizeof(high));
        for(int i=0;i<maxn;i++) f[i]=i;
    }
    
    int GetSet(int p)//获得p节点的根节点
    {
        return (f[p]==p)? p : GetSet(f[p]);
    }
    
    void Merge(int x,int y)//x与y集合合并
    {
        x = GetSet(x);
        y = GetSet(y);
        if(x != y)
        {
    
            if(high[x]>high[y])
            {
                f[y]=x;
            }
            else
            {
                f[x]=y;
                if(high[x]==high[y])high[y]++;
            }
        }
    }
    //这里是主函数
    int main()
    {
        int n, m, k;
        cin >> n >> m >> k;
        int x, y;
        Init();
    
        for(int i = 0; i < m; i++)
        {
            cin >> x >> y;
            Merge(x, y);
        }
        //输出合并之后的数组情况
        for(int i = 1; i <= n; i++)
        {
            if(i != 1) cout << " ";
            cout << f[i];
        }
        cout << endl;
    
        for(int i = 0; i < k; i++)
        {
            cin >> x >> y;
            //如果两个人的“朋友祖先”不相同,证明他们不在同一个朋友圈内,也就不是朋友
            if(GetSet(x) != GetSet(y)) cout << "no" << endl; 
            else cout << "yes" << endl;
        }
        return 0;
    }
    

    给一个测试数据

    7 5 4
    1 3
    2 4
    3 4
    1 4
    5 6
    1 4
    2 3
    2 5
    6 7
    

    结果如下

    4 4 4 4 6 6 7
    yes
    yes
    no
    no
    

    OK

  • 相关阅读:
    Linux下安装配置SVN服务器,windows访问
    Zookeeper集群版搭建
    Zookeeper单机版启动
    Nginx-Session缓存一致性-memcached
    Nginx-配置多台Tomcat-反向代理
    Linux-tomcat-安装启动
    Linux-JDK-环境搭建安装
    Nginx-安装-运行访问页面
    Linux-虚拟机-克隆-学习
    解决CocosCreator 在微信小游戏中使用Socket.io 报错的问题
  • 原文地址:https://www.cnblogs.com/savennist/p/13427568.html
Copyright © 2011-2022 走看看