最小生成树(1)—— Prim算法

【问题描述】

N个村庄之间建立通信联络网,如何选择使得在经费最少的前提下实现全城通信.

【思想分析】

假设U为所有实现通信的村庄的集合,从起点V1开始,此时U={V1},找到U与其它所有顶点权最小的边,并将V3纳入U,然后寻找U={V1,V3}与其他顶点的权最小的边,直到U={V1,V2,V3,V4,V5,V6}.

【代码实现】

首先选用邻接矩阵存储图,两个顶点之间用无穷大表示无连接,用0表示彼此实现通信,其余用权值。此时,选用一个辅助结构数组closedge,包含变量adjvex和lowcost。closedge[i]保存当前状态集合U与顶点Vi之间的信息,即

(closedge[i].adjvex , Vi)=closedge[i].lowcost

这样的话,如果从V1开始的,那么closedge初始状态为:

i 1 2 3 4 5 6
closedge[i].adjvex V1 V1 V1 V1 V1 V1
closedge[i].lowcost  6  1 5    

这时找到最小lowcost=1,将V3纳入集合U中。记住每次纳入新的顶点都要更新一次closedge.

首先将closdge关于新顶点的最小权值lowcost设置为0,然后遍历所有顶点,如果新加入的顶点到某个顶点的边的权值比closedge中记录的更小,就用新加入顶点覆盖原数据(包括adjvex和lowcost)。因为找比如V3的加入使得closedge变为:

i 1 2 3 4 5 6
closedge[i].adjvex V1 V3 V1 V1 V3 V3
closedge[i].lowcost 5 0 5 6 4

重复直到所有的顶点都进入集合U,即完成全城通信.

【详细代码】经codeblocks-13.12调试

  1 #include<iostream>
  2 #define MAX_ARC 1001    //边的最大权值
  3 #define MAX_LINE 400    //图的最大边数
  4 #define MAX_NUM 20      //图的最大顶点数
  5 #define ERROR 0
  6 #define OK 1
  7 using namespace std;
  8
  9 typedef int VertexType;//顶点类型
 10
 11 typedef struct
 12 {
 13     VertexType vexs[MAX_NUM];//记录顶点
 14     int vexnum;
 15     int arcnum;
 16     int arcs[MAX_LINE][MAX_LINE];//记录图
 17 } MGraph;
 18
 19 struct array
 20 {
 21     VertexType adjvex;
 22     int lowcost;
 23 } closedge[MAX_NUM]; //辅助数组,集合U与其他顶点vi的之间的最小边(adjvex,vi)=lowcost
 24
 25 int LocateVex(MGraph G,VertexType u)//根据顶点返回它的位置
 26 {
 27     int i;
 28     for(i=1; i<=G.vexnum; i++)
 29     {
 30         if(G.vexs[i]==u)
 31         {
 32             return i;
 33         }
 34     }
 35     return ERROR;
 36 }
 37
 38 int MiniSpanTree_PRIM(MGraph G,VertexType u)//从顶点u开始
 39 {
 40     int k,i,j;
 41     k=LocateVex(G,u);
 42     if(k==ERROR)
 43         return ERROR;
 44     //初始化closedge[]
 45     for(i=1; i<=G.vexnum; i++)
 46     {
 47         if(i!=k)
 48         {
 49             closedge[i].adjvex=k;//这里不是u
 50             closedge[i].lowcost=G.arcs[k][i];
 51         }
 52     }
 53     closedge[k].lowcost=0;//第k个顶点先进入集合U
 54     if(G.vexnum!=1)
 55         cout<<u<<"->";
 56     else
 57     {
 58         cout<<endl;
 59         return OK;
 60     }
 61
 62     for(i=2; i<=G.vexnum; i++)//剩余vexnum-1个顶点
 63     {
 64         //在closedge[]中遍历并寻找下一个顶点
 65         int temp=MAX_ARC;//遍历记录最小边(adjvex,k)=lowcost
 66         k=0;
 67         for(j=1; j<=G.vexnum; j++)
 68         {
 69             if(closedge[j].lowcost>0&&temp>closedge[j].lowcost)
 70             {
 71                 temp=closedge[j].lowcost;
 72                 k=j;
 73             }
 74         }
 75         //将找到的顶点纳入集合U
 76         cout<<G.vexs[k];
 77         if(i!=G.vexnum)
 78             cout<<"->";
 79         else
 80             cout<<endl;
 81         //更新closedge
 82         closedge[k].lowcost=0;
 83         for(j=1; j<=G.vexnum; j++)
 84         {
 85             if(G.arcs[k][j]<closedge[j].lowcost)
 86             {
 87                 closedge[j].adjvex=k;
 88                 closedge[j].lowcost=G.arcs[k][j];
 89             }
 90         }
 91     }
 92     return OK;
 93 }
 94
 95 int main()
 96 {
 97     MGraph G;
 98     VertexType a,b,u;
 99     int i,j,c;
100     cin>>G.vexnum>>G.arcnum;
101
102     for(i=1; i<=G.vexnum; i++)
103     {
104         for(j=1; j<=G.vexnum; j++)
105         {
106             G.arcs[i][j]=MAX_ARC;
107         }
108     }
109
110     for(i=1;i<=G.vexnum;i++)
111     {
112         cin>>G.vexs[i];
113     }
114
115     for(i=1; i<=G.arcnum; i++)
116     {
117         cin>>a>>b>>c;
118         G.arcs[LocateVex(G,a)][LocateVex(G,b)]=c;
119         G.arcs[LocateVex(G,b)][LocateVex(G,a)]=c;//这句话千万记得加上
120     }
121     cin>>u;
122     MiniSpanTree_PRIM(G,u);
123     return 0;
124 }

【运行结果】不同VertexType的运行结果

【后记】

算法思想提高智商,算法实现积累经验

时间: 2024-10-10 22:37:14

最小生成树(1)—— Prim算法的相关文章

最小生成树(prim算法,Kruskal算法)c++实现

1.生成树的概念 连通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树. 生成树是连通图的极小连通子图.所谓极小是指:若在树中任意增加一条边,则将出现一个回路:若去掉一条边,将会使之变成非连通图. 生成树各边的权值总和称为生成树的权.权最小的生成树称为最小生成树. 2.最小生成树的性质用哲学的观点来说,每个事物都有自己特有的性质,那么图的最小生成树也是不例外的.按照生成树的定义,n 个顶点的连通网络的生成树有 n 个顶点.n-1 条边. 3.构造最小生成树,要解决以下两个问题

最小生成树之Prim算法

Prim算法: 假设N = (V,{E})是连通网,TE是N上最小生成树中边的集合.算法从U={u0}(u0属于V),TE={}开始,重复执行下述操作:在所有u属于U,v属于V-U的边(u,v)属于E中找到一条代价最小的边(u0,v0)并入集合TE,同时v0并入U,直至U=V为止,此时TE中必有n-1条边,则T=(V,{TE})为N的最小生成树. 为实现这个算法,需附设一个辅助数组closedge,以记录从U到V-U具有最小代价的边.对每个顶点vi属于V-U,在辅助数组中存在一个相应分量clos

hihoCoder #1097 最小生成树之Prim算法

原题网址,http://hihocoder.com/problemset/problem/1097 #1097 : 最小生成树一·Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可以拥有不止一个城市了! 但 是,问题也接踵而来——小Hi现在手上拥有N座城市,且已知这N座城市中任意两座城市之间建造道路所需要的费用,小Hi希望知道,最少花费多少就 可以使得任意两座城市都可以通过所建

Hihocoder 之 #1097 : 最小生成树一&#183;Prim算法 (用vector二维 模拟邻接表,进行prim()生成树算法, *【模板】)

#1097 : 最小生成树一·Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可以拥有不止一个城市了! 但是,问题也接踵而来——小Hi现在手上拥有N座城市,且已知这N座城市中任意两座城市之间建造道路所需要的费用,小Hi希望知道,最少花费多少就可以使得任意两座城市都可以通过所建造的道路互相到达(假设有A.B.C三座城市,只需要在AB之间和BC之间建造道路,那么AC之间也是可以通过

hihoCoder - hiho一下 第二十六周 - A - 最小生成树一&#183;Prim算法

题目1 : 最小生成树一·Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可以拥有不止一个城市了! 但是,问题也接踵而来--小Hi现在手上拥有N座城市,且已知这N座城市中任意两座城市之间建造道路所需要的费用,小Hi希望知道,最少花费多少就可以使得任意两座城市都可以通过所建造的道路互相到达(假设有A.B.C三座城市,只需要在AB之间和BC之间建造道路,那么AC之间也是可以通过这两

hihocoder hiho一下 第二十六周 最小生成树一&#183;(Prim算法)

题目1 : 最小生成树一·Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可以拥有不止一个城市了! 但是,问题也接踵而来——小Hi现在手上拥有N座城市,且已知这N座城市中任意两座城市之间建造道路所需要的费用,小Hi希望知道,最少花费多少就 可以使得任意两座城市都可以通过所建造的道路互相到达(假设有A.B.C三座城市,只需要在AB之间和BC之间建造道路,那么AC之间也是可以通过这

hiho一下 第二十六周---最小生成树一&#183;Prim算法

最小生成树一·Prim算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 最近,小Hi很喜欢玩的一款游戏模拟城市开放出了新Mod,在这个Mod中,玩家可以拥有不止一个城市了! 但是,问题也接踵而来--小Hi现在手上拥有N座城市,且已知这N座城市中任意两座城市之间建造道路所需要的费用,小Hi希望知道,最少花费多少就可以使得任意两座城市都可以通过所建造的道路互相到达(假设有A.B.C三座城市,只需要在AB之间和BC之间建造道路,那么AC之间也是可以通过这两条道路连通的

最小生成树的Prim算法

构造最小生成树的Prim算法 假设G=(V,E)为一连通网,其中V为网中所有顶点的集合,E为网中所有带权边的集合.设置两个新的集合U和T,其中集合U用于存放G的最小生成树的顶点,集合T用于存放G的最小生成树中的边.令集合U的初值为U={u0}(假设构造最小生成树时是从顶点u0出发),集合T的初值为T={}.Prim算法的思想是:在连通网中寻找一个顶点落入U集,另外一个顶点落入V-U集的这个顶点加入到U集中,然后继续寻找一顶点在U集而另一顶点在V-U集且权值最小的边放入T集;如果不断重复直到U=V

数据结构--图--最小生成树(Prim算法)

构造连通网的最小生成树,就是使生成树的边的权值之和最小化.常用的有Prim和Kruskal算法.先看Prim算法:假设N={V,{E}}是连通网,TE是N上最小生成树中边的集合.算法从U={u0}(uo属于V),TE={}开始,重复执行下述操作:在所有u属于U,v属于V-U的边(u,v)属于E中找到代价最小的一条边(u0,v0)并入集合TE,同时v0并入U,直至U=V为止.此时TE中必有n-1条边,T={V,{TE}}为N的最小生成树.为实现此算法,需另设一个辅助数组closedge,以记录从U

24最小生成树之Prim算法

最小生成树的Prim算法 思想:采用子树延伸法 将顶点分成两类: 生长点--已经在生成树上的顶点 非生长点--未长到生成树上的顶点 使用待选边表: 每个非生长点在待选边表中有一条待选边,一端连着非生长点,另一端连着生长点 步骤: 步骤1)构造初始待选边表,任选一个顶点v作为初始生长点,对其余每个非生长点w(共n-1个),将边(w,v)加进待选边表,如果边(w,v)不存在,则认为边(w,v)的长度是∞. 步骤2)循环n-2遍,非生长点个数k从n-1变到1. ①选择树边. 从待选边表中选出一条最短的