Kruskal 算法(最小生成树)
来源:互联网 发布:i219v网卡驱动 ubuntu 编辑:程序博客网 时间:2024/05/17 19:14
最小生成树 Minimal Spanning Tree(MST)问题
已知一个连通图G={V,E}(G: graph, V: vector, E: edge),求子图G’={V,E’},使得子图里的边权总和最小。
也就是说,G’ 仍然是一个连通图,但是边的数量要删减。
为什么是最小生成树
假设 G’存在环,那么删去这个环里的任意一条边都不影响整个图的连通性,但边权总和会更小。对了,要补充一点:这个连通图没有负环(但不排除存在负边权)。否则,删去负环中的任何一条边反而会使边权总和变大。
原理
Kruskal算法本质上就是一个贪心算法。
1、将G所有条边按权从小到大排序,MST开始为空。
2、从小到大次序取边(u,v)。
3、若加入边(u,v),MST就有环,则放弃此边,转2。
4、将边(u,v)加入MST,如果已经加了E-1条边,结束。否则转2。
实现方法
最容易想到的方法是暴力,但用并查集的实现则更简洁高效。
在算法原理中,最难实现的就是MST是否有环。这个问题事实上可以转化为 u 和 v 是否在同一连通块里面,这样用并查集则巧妙地解决了该问题,只要判断两个顶点的“祖先”是否相同即可。
另外一点,要证明:当 u 与 v 在不同的连通块时,加入边(u,v)一定是最优的。这一点很简单:在之后的边里面,即使能连通 u 与 v,权值也明显会大于(u,v)的权值。
//Kruskal 算法for (int i=0; i<V; i++) f[i]=i; //并查集初始化sort(edge, edge+E, cmp); //将边按权重排序int MST_edge=0, MST_sum_weight; //MST的边的数量、MST的权重总和 for (int i=0; i<E; i++){ u = find_set(edge[i].u); //找这两个节点的“祖先” v = find_set(edge[i].v); if (u != v) { MST_sum_weight += edge[i].weight; union_set(u, v); //合并两个连通块 MST_edge++; if (MST_edge == E-1) break; //可省,对时间复杂度影响不大 }}
时间复杂度
时间复杂度大约为O(|E|log2|E|+α|V|),α是阿克曼函数的一个增长速度非常缓慢的反函数,在实际运算中不会超过5,因此当作常数也可,这里不再深究。
0 0
- 最小生成树算法(prim&kruskal)
- poj1251最小生成树(kruskal算法)
- 最小生成树 kruskal(算法)
- 最小生成树(Kruskal算法)--poj2421
- 最小生成树(kruskal算法)
- 最小生成树(Kruskal算法)
- Kruskal算法(求最小生成树)
- 最小生成树2(Kruskal算法)
- 最小生成树算法(2)------------Kruskal
- Kruskal 算法(最小生成树)
- 最小生成树算法[Prime/(Kruskal)]
- 最小生成树(二)...Kruskal算法
- kruskal最小生成树(MST)算法
- 最小生成树(kruskal算法)
- 最小生成树-Kruskal算法(模板)
- 最小生成树(Kruskal算法)
- 最小生成树(Kruskal算法)
- 最小生成树(Kruskal算法)模板
- 51nod1449&&Codeforce 552C
- 【LWJGL2 WIKI】【辅助库篇】Slick-Util库:第一部分-读取图片
- Linux多线程实践(5) --Posix信号量与互斥量(解决生产者消费者问题)
- Android之获取view 、window之间的间距区域
- TCP/IP入门--TCP/IP的概念
- Kruskal 算法(最小生成树)
- ZBarReaderView
- 【Windows Form 实战】学生成绩管理系统(二) 数据准备
- 安装windows10和fedora23双系统的一些注意事项
- Linux多线程实践(6) --Posix读写锁(解决读者写者问题)
- XenDesktop中如何重定向USB设备
- Linux多线程实践(7) --Posix条件变量
- uva 10054 项链
- java的throw和throws