目录
概述
一个连通图的生成树是图的极小联通子图,它包含图中所有顶点,并且只含尽可能少的边。这意味着对于生成树来说,若砍去一条边,就会使生成树变成非连通图;若增加一条边,就会形成图中的一条回路。
对于一个带权连通无向图G=(V,E),生成树不同,每棵树的权(即树中所有边上的权值之和)也可能不同。社R为G的所有生成树的集合,若T为R中权值之和最小的那棵生成树,则T成为G的最小生成树。
构造最小生成树有多种算法,但大多数算法是利用了最小生成树的如下性质:
假设G=(V,E)是一个带权连通无向图,U是定点V的一个非空子集。若(u,v)是一条具有最小权值的边,其中u∈U,v∈V-U,则必存在一棵包含边(u,v)的最小生成树。
基于该性质的最小生成树算法主要有:Prim算法和Kruskal算法,它们都基于贪心算法的策略。
普里姆(Prim)算法
Prim算法的执行非常类似于寻找图的最短路径的Dijkstra算法(见http://blog.csdn.net/u013161323/article/details/53931770)。假设N={V,E}是连通图,Et是N上最小生成树中边的集合。算法从Vt={u0}(u0∈V),Et={}开始,重复执行下述操作:
在所有u∈Vt,v∈V-Vt的边(u,v)∈E中找出一条代价最小的边(u0,v0)并入集合Et,通知将v0并入Vt,直至Vt=V为止。此时Et中必有n-1条边,则T=(Vt,Et)为N的最小生成树。
具体的过程如下所示:
克鲁斯卡尔(Kruskal)算法
与Prim算法从定点开始扩展最小生成树不同,Kruskal算法是一种按权值的递增次序选择合适的边来构造最小生成树的方法。假设N=(V,E)是连通图,对应的最小生成树T=(Vt,Et),Kruskal算法的基本步骤如下:
初始化:Vt=V,Et=∅。即每个顶点构成一棵独立的树,T此时是一个仅含|V|个顶点的森林;
循环(重复下列操作直至T是一棵树):按G的边的权值递增顺序依次从E-Et中选择一条边,如果这条边加入T后不构成回路,则将其加入Et,否则舍弃,直至Et中含有n-1条边。
具体过程如下所示: