最小生成树问题:一个具有N个顶点的连通图,以及若干条边(至少N-1条),如何在这些边中选出N-1条连接N个顶点,并使这N-1条边的权值和最小,即代价最小。一个比较形象的描述就是有N个城市,如何建一个交通网连接N个城市,使代价最低。
一、MST性质
首先需要介绍一下MST性质:假设一个连通图,U是顶点集的一个真子集,若(u,v)是一条具有最小权值的边,其中u∈U,v∈V-U,则必存在一棵包含边(u,v)的最小生成树。
证明:假设有一棵不包含边(u,v)的最小生成树T,将边(u,v)加入到T中。由于T是最小生成树,N个顶点相通,T中必有一条边(u',v'),u'∈U,v'∈V-U,且u和u',v和v'之间必有路径相同,则删掉(u',v'),得到另一棵生成树T'。由于(u,v)的权值不大于(u',v')的权值,所以T'的代价不高于T,所以T'是一棵包含(u,v)的最小生成树。
最小生成树的两种算法,Prim算法和Kruskal算法。
二、Prim算法
1、算法过程:
步骤一:任选一个顶点u_0∈V,加入到U中,TE={}存放最小生成树的集合。
步骤二:在所有的u∈U,v∈V-U中选择代价最小的边(u_0,v_0)加入到TE,并将v_0加入到U中。
步骤三:重复步骤二直至U=V,此时TE中必有N-1条边,求得一棵最小生成树。
这是典型的贪心算法,每次都去寻找一条权值最小的边。
2、代码实现:
https://blog.csdn.net/feilong_csdn/article/details/69367374
3、算法分析:算法复杂度是O(N^2),只与顶点数有关,适合边稠密图的最小生成树求解。
三、Kruskal算法
1、算法过程:
步骤一:初始状态,N个顶点,0条边的不连通图,TE={}存放最小生成树的集合。
步骤二:选择未使用边中最小的边,若该边所对应的两个顶点不在同一连通分量上(通俗点说,就是当前两个顶点不相通),则将该边放入到TE中,否则舍弃该边。
步骤三:重复步骤二,直至所有的顶点都在同一连通分量上,或者说找到了N-1条边。
同样也是贪心算法。
2、代码实现
https://blog.csdn.net/afei__/article/details/83316587
3、算法分析:如果采用堆来存放所有边,则每次选择最小代价的边的时间复杂度仅需O(log e),所以时间复杂度为O(e*log e),适合稀疏连通图的最小生成树的实现。