1、概述:设G=(V,E)是无向连通带权图,即一个网络。E中每条边(v,w)的权为c[v][w]。如果G的子图G~是一颗包含G的所有顶点的树,则称G~为G的生成树。并且生成树上面的各边权的总和称为该生成树的耗费。所以在所有的G的生成树中,消耗最小的生成树就是G的最小生成树。

2、最小生成树性质:其中Prim和Kruskal算法都是可以看做设计贪心算法策略的例子。

设G=(V,E)是一个连通网络,U是顶点集V的一个非空真子集。若(u,v)是G中一条“一个端点在U中(例如:u∈U),另一个端点不在U中的边(例如:v∈V-U),且(u,v)具有最小权值,则一定存在G的一棵最小生成树包括此边(u,v)。

3、Prim算法:设置G=(V,E)是连通的带权图,V={1,2,。。。,n}。构造G的最小生成树的Prim算法的基本思想是:首先置S={1},然后,只要S是V的真子集,就进行该贪心选择吧:选取满足条件的i属于S,j属于V-S,且c[i][j]最小的边,将顶点j添加到S中。所以最后进行到S=V为止即可。

下面贴出Prim算法的代码段:

public static void prim(int n,float[][] c){
//prim算法
float[] lowcost = new float[n+1];
int[] closest = new int[n+1];
boolean[] s = new boolean[n+1];
s[1] = true;
for(int i =2;i<=n;i++){
lowcost[i] = c[1][i];
closest[i] = 1;
s[i] = false;
}

for(int i =1;i<n;i++){
float = min = Float.MAX_VALUE;
int j = 1;
for(int k =2;k<=n;k++){
if((lowcost[k]<min)&&(!s[k])){
min = lowcost[k];
j = k;
s[j] = true;
for(int k = 2;k<=n;k++)
if((c[j][k] < lowcost[k])&&(!s[k])){
lowcost[k] = c[j][k];
closest[k] = j;
}
}
}
所以上述的prim所需要的计算时间为O(n2)。

4、KrusKal算法:当图的边数为e时,KrusKal算法的所需要的时间是O(eloge)。当e=O(n2)时,该算法要比Prim算法差一些,但是当e=o(n2)时,该算法要好得多。

  我们给定无向连通带权图G=(V,E),V={1,2,。。。,n}。KrusKal算法构造的思想为:首先将n个顶点看作是n个孤立的分支。将所有边按照权值大小从小到大的排序,从第一条边开始依次顺序的查看每一条边,当查看到第k条边(v,w)时,如果端点v和w分别是当前两个不同的连通分支T1和T2中的顶点时,就使用边(v,w)将T1和T2连接成为一个连通分支,然后继续查看第k+1条边;如果端点v和w在当前的同一个连通分支中,就直接在查看第k+1条边。这个过程进行到只剩下一条边为止即可,此时这个连通分支就是G的一颗最小生成树。