算法简介
Prim算法采用与Dijkstra、Bellmaxn-Ford算法一样的“蓝白点”思想:白点代表已经进入最小生成树的点,蓝点代表未进入最小生成树的点。
算法描述
以1为起点生成最小生成树。
minn[v]表示蓝点v与白点相连的最小边权。
sum表示最小生成树的权值之和。
初始化
minn[v]=oo(v!=1)
minn[1]=0
sum=0
简单的过程
for(int i-1;i<=n;i++)
寻找minn[v]最小的蓝点u;
将u标记为白点;
sum+=minn[u];
for(与白点相连的所有蓝点v)
if(w[u][v]<minn[v]) minn[v]=w[u][v];
算法结束sum即为最小生成树的权值和
算法证明
- 当只取了一个点K时(边集为空),一定存在一个sum,包含当前的点集和边集。
- 假设一个sum存在当前的点集和边集。当前点集为S,剩下的点集为S’,设跨越S和S’的最小代价的边为(u,v)
反证法
假设取的是跨越S——S’的某边(u’,v’),删除(u’,v’)加入(u,v),S和S’分别联通,且S——S’通过(u,v)也能联通,还得到了一个权值更小的sum。所以新加入的边一定是代价最小的边(u,v)
根据1,2,Prim算法的正确性得证。
算法分析&思想解析
分析
Prim算法每次循环都将一个蓝点u变为白点,并且此蓝点u与白点相连的最小边权minn[u]还是当前蓝点中最小的。这样就相当于向生成树中添加了n-1此最小边,最后得到的一定是最小生成树。
模拟
蓝点和虚线表示未进入最小生成树的点、边。
白点和实线表示已经入最小生成树的点、边。
1
初始时所有点都是蓝点,minn[1]=0,minn[2、3、4、5]=oo,权值之和sum=0
2
第一次循环自然是找到minn[1]=0最小的蓝点1.将1变为白点,接着枚举与1相连的所有蓝点2、3、4,修改它们与白点相连的最小边权。
3
第二次循环是找到minn[2]最小的蓝点2.将2变为白点,接着枚举与2相连的所有蓝点3、5,修改它们与白点相连的最小边权。
4
第三次循环是找到minn[3]最小的蓝点3.将3变为白点,接着枚举与3相连的所有蓝点4、5,修改它们与白点相连的最小边权。
5
最后两轮循环将点4,5及边w[2][5]、w[3][4]添加到最小生成树中
最后权值之和sum为6
小结
这n次循环,每次循环我们都能让一个新的点加入生成树,n次循环就能把