• 最小生成树——Kruskal算法


    先上最小生成树定义:

    在一个给定的无向图G=(V,E)中, (u,v)代表连接顶点u和v的边,而w(u,v)代表这个边的权重。若存在T为E的子集,且为无循环图,使得

    中的w(T)最小,则这个T为G的最小生成树(MST)

    最小生成树的几个性质:

    • 最小生成树的边数必然是顶点数减一,|E| = |V| - 1。
    • 最小生成树不可以有循环。
    • 最小生成树不必是唯一的。

    求解一个图的最小生成树有很多算法,这里介绍Kruskal算法。

    算法的执行过程可以描述为:

    1.将图中所有的边按照从小到大的顺序排序

    2.从小到大依次考察每条边(u,v)是否要当前的生成树集中。考查结果分为两种情况:

      case 1: u和v在同一连通分量中,那么加入(u,v)后会形成环,因此要放弃这种情况.

      case 2: u,v不在同一连通分量中,那么加入边(u,v)一定是最优的。证明可以用cut&paste来解释。

    3.对每一条边循环第二步,直到加入的边的数目=顶点数目-1(即形成了树)

    根据上面的过程可以得到伪代码:

    Kruskal:

     将所有边排序,记第i小的边为e[i](1<=i<m)

    初始化MST为空

    初始化连通分量,让每个点成为一个独立的连通分量

    for(int i=0;i<m;i++)

      if(e[i].u和e[i].v不在同一连通分量中)

      {

        把边e[i]加入MST

        合并e[i].u和e[i].v所在的连通分量

      }

    END

    由上面伪代码我们可以看出,问题的关键是连通分量的查询和合并,自然我们就能想到高效的解决方案是并查集.

    由此我们给出完整的代码:

    假设第i条边的两个端点序号和权值分别保存在u[i],v[i]和w[i]中,而排序后第i小的边的序号保存在r[i]中(这里先将原顺序的序号放在r[i]中,然后按照w[i]来排序,排完后r[i]就是按照从小到大的序号排列的了——这称为间接排序!)

    int cmp(const int i, const int j){   return w[i]<w[j]; }
    int find(int x)
    {
        if(x!=father[x]) return father[x]=find(father[x]);
        return x;
    }
    int Kruskal()
    {
        int total=0,count=0;
        //对n个顶点初始化并查集
        for(int i=0;i<n;i++) 
            father[i]=i;
        //初始化序号记录集
        for(int i=0;i<m;i++)
              r[i]=i;
        sort(r,r+m,cmp);
        for(int i=0;i<m;i++)//对每一条边来考查
        {
            int e = r[i];
            int ru = find(u[e]);
            int rv = find(v[e]);
            if(ru!=rv)
           {
                total+=w[e];
                count++;
                father[rv] =ru;
            } 
             if(count=n-1) break;
         }
        return total;
    }

    由此由并查集实现的Kruskal算法就搞定了!

  • 相关阅读:
    Linux 安装中文man手册
    centos6.9使用NTFS-3G挂载ntfs文件系统
    Linux基础知识之挂载详解(mount,umount及开机自动挂载)
    技术点总结
    SQL 分组后获取其中一个字段最大值的整条记录 【转载】
    线程池之ThreadPool类与辅助线程
    Task.Run使用默认线程池
    VS生成事件
    线程池之ThreadPoolExecutor使用
    Sql笔记
  • 原文地址:https://www.cnblogs.com/soyscut/p/3253532.html
Copyright © 2020-2023  润新知