zoukankan      html  css  js  c++  java
  • 最小生成树——Kruskal算法、Prim算法

    树:连通的、无环的无向图。
    特征:n个结点,n-1条无向边,且连通。任意两点之间的路径唯一。填边一条边就会产生环。
    生成树:无向连通图的包含所有顶点的极小连通子图。
    最小生成树:各边权值总和最小的生成树。

    Kruskal算法
    1:按照权重从小到大给边排一个序
    2:首先创建一个无边的图,并且可以相互到达的结点在同一个集合中(使用并查集来实现),那么初始状态每个结点都是一个单独的集合(因为初始只有结点,还没有放入边)
    3:按照之前从小到大排序之后的边,按照从小到大进行遍历,若是当前遍历的边的两端结点没有在同一个集合中,那么这条边就在最小生成树中,并且将边的两端结点的两个集合合并为一个集合;若是在同一个集合中,那么这条边就不再最小生成树中,那么这条边对最后的结果就没贡献。
    4:直到遍历到n-1条有效边为止。若是所有的边都遍历完但是没有找到n-1条有向边,那么这个图就不可能组成最小生成树。
    注:最小生成树可能并不会唯一,但是最小生成树的总权值一定唯一。
    时间复杂度:O(eloge),适用于洗漱图

    Prim算法
    将图的顶点分为两个部分:处理完的顶点、未处理的顶点
    从处理完的顶点中选取一个拓展一个未处理的顶点。对一个只有结点的图加边操作
    1:任选一个结点假如到处理完的集合中。初始,处理完的集合中只有一个结点
    2:找到两个连接两个集合的最短边,将其加入到图中。并把它的未处理的顶点加入到处理完的集合中。可以给每个顶点记录一个权值,表示和它关联的从处理过的顶点射出的最短边权(初始为无穷大)。
    3:之后每一次只需要遍历未处理的顶点,把其中权值最小点的标记为已处理,接着更新和它邻接的顶点就可以了。可以使用优先队列实现。加入的边的两个端点不在同一个集合中。这个可以使用一个数组来标记该结点是否被处理过。
    4:直到所有的结点都被标记了。否则那么这个图就不会有最小生成树

    复杂度:O(v^2),适用于稠密图。使用优先队列,复杂度为O(vlogv)

     Prim与dijkstra的区别:从算法的描述上和算法的实现上二者都是非常的相似,但是仍然有点细微的区别。这两个算法的核心思想都是将点分为处理过的点的集合U,未处理过的点的集合V.但是Prim每次找的是U-V之间的最短路,而dijkstra找的是源点s到V之间的最短路。所以还是有点细微区别的。

    写于:2020/8/15 8:01


    作者:孙建钊
    出处:http://www.cnblogs.com/sunjianzhao/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    pch文件的创建
    常用的Xcode插件下载地址
    内存管理
    学习笔记-static的作用
    IOS 之label的自适应
    OC中的循环引用
    理解事务的4种隔离级别
    Solrcloud集群搭建
    常见前端浏览器兼容问题及解决方案
    Java内存溢出详解及配置
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/13507423.html
Copyright © 2011-2022 走看看