最小生成树

举报
兔老大 发表于 2021/04/22 23:25:59 2021/04/22
【摘要】 问题提出:     要在n个城市间建立通信联络网。顶点:表示城市,权:城市间通信线路的花费代价。希望此通信网花费代价最小。 问题分析:     答案只能从生成树中找,因为要做到任何两个城市之间有线路可达,通信网必须是连通的;但对长度最小的要求可以知道网中显然不能有圈,如果有圈,去掉一条边后,并不破...

问题提出:
    要在n个城市间建立通信联络网。顶点:表示城市,权:城市间通信线路的花费代价。希望此通信网花费代价最小。
问题分析:
    答案只能从生成树中找,因为要做到任何两个城市之间有线路可达,通信网必须是连通的;但对长度最小的要求可以知道网中显然不能有圈,如果有圈,去掉一条边后,并不破坏连通性,但总代价显然减少了,这与总代价最小的假设是矛盾的。
结论:
    希望找到一棵生成树,它的每条边上的权值之和(即建立该通信网所需花费的总代价)最小 —— 最小代价生成树。
    构造最小生成树的算法很多,其中多数算法都利用了一种称之为 MST 的性质。
    MST 性质:设 N = (V, E)  是一个连通网,U是顶点集 V的一个非空子集。若边 (u, v) 是一条具有最小权值的边,其中u∈U,v∈V-U,则必存在一棵包含边 (u, v) 的最小生成树。


(1)普里姆 (Prim) 算法

算法思想: 
    ①设 N=(V, E)是连通网,TE是N上最小生成树中边的集合。
    ②初始令 U={u_0}, (u_0∈V), TE={ }。
    ③在所有u∈U,u∈U-V的边(u,v)∈E中,找一条代价最小的边(u_0,v_0 )。
    ④将(u_0,v_0 )并入集合TE,同时v_0并入U。
    ⑤重复上述操作直至U = V为止,则 T=(V,TE)为N的最小生成树。

 
代码实现:


  
  1. void MiniSpanTree_PRIM(MGraph G,VertexType u)
  2.     //用普里姆算法从第u个顶点出发构造网G的最小生成树T,输出T的各条边。
  3.     //记录从顶点集U到V-U的代价最小的边的辅助数组定义;
  4.     //closedge[j].lowcost表示在集合U中顶点与第j个顶点对应最小权值
  5. {
  6.     int k, j, i;
  7.     k = LocateVex(G,u);
  8.     for (j = 0; j < G.vexnum; ++j)    //辅助数组的初始化
  9.         if(j != k)
  10.         {
  11.             closedge[j].adjvex = u;
  12.             closedge[j].lowcost = G.arcs[k][j].adj;    
  13. //获取邻接矩阵第k行所有元素赋给closedge[j!= k].lowcost
  14.         }
  15.     closedge[k].lowcost = 0;        
  16. //初始,U = {u};  
  17.     PrintClosedge(closedge,G.vexnum);
  18.     for (i = 1; i < G.vexnum; ++i)    \
  19. //选择其余G.vexnum-1个顶点,因此i从1开始循环
  20.     {
  21.         k = minimum(G.vexnum,closedge);        
  22. //求出最小生成树的下一个结点:第k顶点
  23.         PrintMiniTree_PRIM(G, closedge, k);     //输出生成树的边
  24.         closedge[k].lowcost = 0;                //第k顶点并入U集
  25.         PrintClosedge(closedge,G.vexnum);
  26.         for(j = 0;j < G.vexnum; ++j)
  27.         {                                           
  28.             if(G.arcs[k][j].adj < closedge[j].lowcost)    
  29. //比较第k个顶点和第j个顶点权值是否小于closedge[j].lowcost
  30.             {
  31.                 closedge[j].adjvex = G.vexs[k];//替换closedge[j]
  32.                 closedge[j].lowcost = G.arcs[k][j].adj;
  33.                 PrintClosedge(closedge,G.vexnum);
  34.             }
  35.         }
  36.     }
  37. }


(2)克鲁斯卡尔 (Kruskal) 算法

算法思想: 
    ①设连通网  N = (V, E ),令最小生成树初始状态为只有n个顶点而无边的非连通图,T=(V, { }),每个顶点自成一个连通分量。
    ②在 E 中选取代价最小的边,若该边依附的顶点落在T中不同的连通分量上(即:不能形成环),则将此边加入到T中;否则,舍去此边,选取下一条代价最小的边。
③依此类推,直至 T 中所有顶点都在同一连通分量上为止。
      
    最小生成树可能不惟一!

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/87823689

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。