最小生成树

---恢复内容开始---

 

最小生成树的算法分为 prim和kruscal算法

 

初始状态:

 

设置2个数据结构:

lowcost[i]:表示以i为终点的边的最小权值,当lowcost[i]=0说明以i为终点的边的最小权值=0,也就是表示i点加入了MST

mst[i]:表示对应lowcost[i]的起点,即说明边<mst[i],i>是MST的一条边,当mst[i]=0表示起点i加入MST

 

我们假设V1是起始点,进行初始化(*代表无限大,即无通路):

 

最小生成树

 

 

lowcost[2]=6,lowcost[3]=1,lowcost[4]=5,lowcost[5]=*,lowcost[6]=*

mst[2]=1,mst[3]=1,mst[4]=1,mst[5]=1,mst[6]=1,(所有点默认起点是V1)

 

明显看出,以V3为终点的边的权值最小=1,所以边<mst[3],3>=1加入MST

 最小生成树

 

此时,因为点V3的加入,需要更新lowcost数组和mst数组:

lowcost[2]=5,lowcost[3]=0,lowcost[4]=5,lowcost[5]=6,lowcost[6]=4

mst[2]=3,mst[3]=0,mst[4]=1,mst[5]=3,mst[6]=3


明显看出,以V6为终点的边的权值最小=4,所以边<mst[6],6>=4加入MST

最小生成树

 

 


此时,因为点V6的加入,需要更新lowcost数组和mst数组:

lowcost[2]=5,lowcost[3]=0,lowcost[4]=2,lowcost[5]=6,lowcost[6]=0

mst[2]=3,mst[3]=0,mst[4]=6,mst[5]=3,mst[6]=0


明显看出,以V4为终点的边的权值最小=2,所以边<mst[4],4>=4加入MST

 最小生成树

 


此时,因为点V4的加入,需要更新lowcost数组和mst数组:

lowcost[2]=5,lowcost[3]=0,lowcost[4]=0,lowcost[5]=6,lowcost[6]=0

mst[2]=3,mst[3]=0,mst[4]=0,mst[5]=3,mst[6]=0


明显看出,以V2为终点的边的权值最小=5,所以边<mst[2],2>=5加入MST

 

最小生成树

 


此时,因为点V2的加入,需要更新lowcost数组和mst数组:

lowcost[2]=0,lowcost[3]=0,lowcost[4]=0,lowcost[5]=3,lowcost[6]=0

mst[2]=0,mst[3]=0,mst[4]=0,mst[5]=2,mst[6]=0


很明显,以V5为终点的边的权值最小=3,所以边<mst[5],5>=3加入MST


lowcost[2]=0,lowcost[3]=0,lowcost[4]=0,lowcost[5]=0,lowcost[6]=0

mst[2]=0,mst[3]=0,mst[4]=0,mst[5]=0,mst[6]=0


至此,MST构建成功,如图所示:

 

最小生成树

 

最小生成树
 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 #define MAX 100
 6 #define MAXCOST 0xfffffff
 7 
 8 int graph[MAX][MAX];
 9 int lowcost[MAX];
10 int mst[MAX];
11 int n,sum = 0;
12 
13 int prim()
14 {
15     int min,minid;
16     for (int i=2;i<=n;i++)
17     {
18         lowcost[i] = graph[1][i];
19         mst[i] = 1;
20     }
21     mst[1] = 0;
22     for (int i=2;i<=n;i++)
23     {
24         min = MAXCOST;
25         minid = 0;
26         for (int j=2;j<=n;j++)
27         {
28             if (lowcost[j] < min && lowcost[j]!=0)
29             {
30                 min = lowcost[j];
31                 minid = j;
32             }
33         }
34         sum += min;
35         lowcost[minid] = 0;
36         for (int j=2;j<=n;j++)
37         {
38             if (graph[minid][j] < lowcost[j])
39             {
40                 lowcost[j] = graph[minid][j];
41                 mst[j] = minid;
42             }
43         }
44     }
45     return sum;
46 }
47 
48 int main()
49 {
50     int m;
51     cin >> n >> m;    // n代表图的顶点,m代表图的边
52     //初始化图
53     for (int i=1;i<=n;i++)
54     {
55         for (int j=1;j<=n;j++)
56         {
57             graph[i][j] = MAXCOST;
58         }
59     }
60     //构造图
61     for (int k=1;k<=m;k++)
62     {
63         int i,j,cost;
64         cin >> i >> j >> cost;
65         graph[i][j] = graph[j][i] = cost;
66     }
67     cout << prim() << endl;
68     return 0;
69 }
View Code

 

kruscal算法 是使用了并查集。始终选择当前可用的最小边权的边(可以直接快排或者algorithm的sort)。每次选择边权最小的边链接两个端点是kruskal的规则,并实时判断两个点之间有没有间接联通。

 

同样的,模拟过程

最小生成树

对权值进行排序,随后选取最小对权值的边。

排序后,最小的边自然是第8条边,于是4和6相连

最小生成树

遍历继续,第二小的边是1号,1和2联通。

最小生成树

再继续

最小生成树

继续

最小生成树

 

其次是dis为15的边4,但是2和4已经相连了,pass。

然后是dis为16的两条边(边2和边9),边2连接1和3,边9连接3和6,它们都已经间接相连,pass。

再然后就是dis为22的边10,它连接5和6,5还没有加入组织,所以使用这边。继续,发现此时已经连接了n-1条边,结束,最后图示如下:

最小生成树

 

 

 

该博客借鉴了许多别的博客,之所以写成自己的只是方便自己现在去理解和今后复习

 

上一篇:使用python实现单链表


下一篇:(原创)最小生成树之Prim(普里姆)算法+代码详解,最懂你的讲解