最小生成树-MST算法详解及代码实现

转载 2015年11月19日 16:36:23

from http://blog.csdn.net/coder_oyang/article/details/48195405

师兄发了一篇CCF-C类的文章,但是那个会议在澳洲排名属于B类,他说他在CVPR的某一篇文章的基础之上用了MST算法,避免了局部最优解,找到了全局最优解,实验结果比原文好很多,整个文章加实验前后仅仅做了2周。真是羡煞旁人也。。其实在机器学习当中,经常会遇到局部最优解的问题,所以,就花了点时间看看MST,兴许我也能找点灵感呢,呵呵..

看完最小生成树之后得到的一个想法就是:其实MST就是一种贪心算法,每一步选择都是选取当前候选中最优的一个选择。下面详细谈谈我认识的最小生成树吧

1. 最小生成树解决什么样的问题

城市之间建设道路的问题,首先,因为道路照价较高所以我们希望总的道路是最短的;其次,我们希望造的路在每个城市之间不会形成环路。那么MST的数学表达式就是这样,期望在图 G(V,E) 中找到一个子集 T 使得,使得造价函数w(T) 最小

2. MST 伪代码

在算法导论中对最小生成树的伪代码是这样描述的:

GENERIC(G,w){
A = empty
while A does not form a spanning tree
        find an edge (u,v) that is safe for A
        A = A & (u,v)
return A
}

算法的核心是在找到一条对于集合A安全的边。那么如何定义“安全”呢?

  • 安全边

先要定义一个名词:切割:无向图 G=(V,E) (V代表图中的结点,E代表图中两个节点之间的边) 的一个切割就是 (S , V-S) 就是集合V 的一个切割。

如上图就是图 G 的一个切割实例,如果图中的某一条边 (u,v) 的一个端点位于集合 S 中,另一个端点位于 V-S 中,那么这条边横跨切割 (S , V-S)。如果集合 A 中不存在这样的横跨边,那么该切割尊重集合 A 。在横跨一个切割的所有边中,权重最小的边称为轻量级边。上图中红色结点属于集合 S ,白色结点属于集合 V-S ,横跨改切割的边是那些连接红色与白色结点的边,边 (c,d) 是横跨改切割的唯一一条轻量级边。其中红色边属于子集 A :注意切割 (S , V-S) 尊重集合A,因为集合 A 中没有横跨改切割的边。那么安全边的定于有如下定义
设G=(V , E) 是一个在边E上定义了实数权值函数 w 的的连通无向图。设集合 A 为 E 的一个子集,且 A 包括在图G的某棵最小生成树中,设 (S , V-S) 是图G中尊重集合A的任意一个切割,又设 (u,v) 是横跨切割 (S,V-S) 的一条轻量级边。那么边 (u,v) 对于集合 A 是安全的。

3. MST实现算法:Kruskal \ Prim

前文分析了MST算法核心:如何寻找安全边。这里有两种经典算法,一是Kruskal 算法,另一个是Prim算法,先来看看Kruskal 算法是如何找安全边的。

3.1 Kruskal 算法

Kruskal 算法找到安全边的想法在所有连接森林中两棵不同树的边里面,找到权重最小的边 (u,v) 。假设C1和C2为边 (u,v) 所连接的两棵树。由于边 (u,v) 一定是连接C1和其他某棵树的一条轻量级边,那么 (u,v) 一定是条安全边。

MST-KRUSKAL(G,w){
    A= NULL
    for each vector v in G.V
         MAKE-SET(v)
    sort the edges of G.E into nondecreasing order by weight w
    for each edge(u,v) in G.E, taken in nondecreasing order by weight
         if FIND-SET(v) != FIND-SET(u)
            A = A & {(u,v)}
            UNION(u,v)
    return A
}

说明:FIND-SET(v) != FIND-SET(u) 判断结点 u , v 是否属于同一棵树,下面是执行Kruskal算法的过程,红色的边属于不断增长的森林A。该算法按照边的权值大小一次进行考虑,箭头所指的边是算法每一步所考察的边。如果该条边将两棵不同的树连接起来,它就被加入到森林里面去,从而完成对两棵树的合并。

总结Kruskal 算法:1: 连接的是两颗不同的树   2:选取的是轻量级边   循着这两个条件便实现Kruskal 算法

算法代码见 算法导论 19-2 采用二项堆的最小生成树算法

3.2 Prim 算法

Prim算法所具有的一个性质是集合 A 中的边总是构成一棵树。从任意的根结点出发,一直长大到覆盖 V 中的所有结点为止。算法每一步在连接集合A与A之外的结点的所有边中,选择一条轻量级边加入到 A 中,下面是执行Prim算法的过程

其中红色边与结点都属于树A。在每一步算法中,树的结点就决定了图的一个切割,横跨该切割的一条轻量级边被加入到树中。


参考文献

算法导论 Thomas H. et.al


最小生成树-MST算法详解及代码实现

最小生成树,贪心算法,Kruskal,Prim算法
  • coder_oyang
  • coder_oyang
  • 2015年09月03日 16:34
  • 4555

算法之详解最小生成树

算法之详解最小生成树 分类: Algorithms & Data Structure2012-05-01 00:20 9160人阅读 评论(31) 收藏 举报 算法algorith...
  • u014774781
  • u014774781
  • 2015年06月12日 20:02
  • 1764

图论-最小生成树(MST)算法

最小生成树:E = V - 1 无权图的最小生成树不必关心边的长度,而是要找到最少数量的边。 最小生成树于搜索算法几乎是相同的,同样可以给予深度优先搜索和广度优先搜索。 DFS算法访问所有的顶点...
  • cdl2008sky
  • cdl2008sky
  • 2011年11月16日 15:05
  • 4064

图的最小生成树MST--Prim算法

带权值的网图通常会遇到这样一个问题:得到一个tuzho
  • dreamhougf
  • dreamhougf
  • 2014年09月17日 17:43
  • 748

[对偶 KM算法 生成树 || 最大费用可行流 || 线性规划] BZOJ 1937 [Shoi2004]Mst 最小生成树

树边减,非树边加,wi表示i号边原来的边权,di表示i号边的改变量 对于一条非树边,覆盖所有树边,都要满足:wi−di≤wj+dj 得wi−wj≤di+dj 这样的话d就是KM算法里的顶标 跑最大匹配...
  • u014609452
  • u014609452
  • 2016年07月04日 18:44
  • 418

最小生成树(MST,minimum spanning tree)

生成树:由图生成的树,由图转化为树,进一步可用对树的相关操作来对图进行操作。最小指的是权值最小;生成树是边的集合,如下图所示的最小生成树:MST={{a,b},{a,f},{f,c}}\text{MS...
  • lanchunhui
  • lanchunhui
  • 2016年09月02日 08:12
  • 593

【算法】图论_最小生成树(MST)_Kruskal

最小生成树(MST),即最小权值生成树,一般是无向图中的概念。 生成树是原图的这样一个子图 没有回路,即n个点最多有n-1条边 所有点连通,这下好了,最少也要有n-1条边 正是因为它无向无环连通,所...
  • dogsaur
  • dogsaur
  • 2013年08月02日 12:37
  • 598

最小生成树(MST)求解旅行商问题

从当前位置开始(也可以不指定起始位置),访问完所有未访问的端点后返回起始点的最短路径就是连接所有端点的生成树。最小生成树需保证: 每条边最多只能被选 1 次; 抹掉所有未被选择的边时,图形不能分为上下...
  • lanchunhui
  • lanchunhui
  • 2016年09月11日 15:34
  • 1371

最小生成树之MST性质

在数据结构上看到这个性质的时候并不是很理解,觉得很抽象,所以我决定记录一下,以免以后又不理解了。其实就是一个 最优选择问题。原性质描述如下: 假设N = (V,{ E })是一个连通网,U 是顶点...
  • shagua_nan
  • shagua_nan
  • 2016年03月20日 14:18
  • 1194

最小生成树(MST)三种实现方法C++版本

代码如下: #include #define MAXN 100 using namespace std ; ifstream cin("test.txt") ; ofstream cout("...
  • jasonkent27
  • jasonkent27
  • 2015年03月06日 21:50
  • 528
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:最小生成树-MST算法详解及代码实现
举报原因:
原因补充:

(最多只允许输入30个字)