最小生成树(Prim算法+Kruskal算法)
什么是最小生成树(MST)?
给定一个带权的无向连通图,选取一棵生成树(原图的极小连通子图),使生成树上所有边上权的总和为最小,称为该图的最小生成树。
求解最小生成树的算法一般有这两种:Prim算法和Kruskal算法。
Prim算法(普里姆算法)
图的存贮结构采用邻接矩阵。此方法是按各个顶点连通的步骤进行,需要用一个顶点集合,开始为空集,以后将以连通的顶点陆续加入到集合中,全部顶点加入集合后就得到所需的最小生成树。
简单描述:
1.初始化:Vnew = {x},其中x为集合V中的任一节点(作为起始点),Enew = {},为空。
2.在边集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一)。将v加入集合Vnew中,将<u, v>边加入集合Enew中。
3.重复操作2直至Vnew = V。
代码展示:
#include<iostream> #include<cstdio> #include<cstring> using namespace std;const int INF=0x3f3f3f3f; const int N=101;int G[N][N];//邻接矩阵 int Lowest[N];//表示和已选顶点集Vnew的最小距离,Lowest[i]=0表示点i已经在Vnew中 int n,m;int prim() {int Num=0;//最小生成树权值for(int i=2;i<=n;i++)//选取第一个点开始Lowest[i]=G[1][i];//取第一行权值for(int i=1;i<n;i++)//找到新顶点加入(n-1个) {int minid=0;int mindis=INF;for(int j=2;j<=n;j++)//找到距离最小的 {if(Lowest[j]!=0&&Lowest[j]<mindis){mindis=Lowest[j];minid=j;}}Num+=mindis;Lowest[minid]=0;//把点minid加入Vnewfor(int j=2;j<=n;j++)//更新Lowest数组if(Lowest[j]>G[minid][j])Lowest[j]=G[minid][j];}return Num; }int main() {while(~scanf("%d%d",&n,&m)){memset(G,0x3f,sizeof(G));//初始化为最大值for(int i=1;i<=n;i++)//对角线为0G[i][i]=0;int u,v,w;for(int i=1;i<=m;i++){scanf("%d%d%d",&u,&v,&w);G[u][v]=G[v][u]=w;}int MST=prim();//计算最小生成树总权值 printf("%d\n",MST);} }
View Code
Kruskal算法(克鲁斯卡尔算法)
图的存贮结构采用边集数组,且权值相等的边在数组中排列次序可以是任意的。该方法对于边相对比较多的不是很实用,浪费时间。思想是贪心思想。
方法:将图中的边按其权值由小到大的次序顺序选取,若选边后不形成回路,则保留作为一条边,若形成回路则除去。依次选够(n-1)条边,即得最小生成树。(n为顶点数)
首先我们把所有的边按照权值先从小到大排列,接着按照顺序选取每条边,如果这条边的两个端点不属于同一集合,那么就将它们合并,直到所有的点都属于同一个集合为止。至于怎么合并到一个集合,那么这里我们就可以用到一个工具——-并查集(不知道的同学请移步:Here)。换而言之,Kruskal算法就是基于并查集的贪心算法。
代码展示:
#include <cstdio> #include <cstdlib> #define MAXN 10010 using namespace std;int Uset[MAXN];//并查集 int Rank[MAXN];//秩 typedef struct{int a, b, price; }Node; Node edge[MAXN];int cmp(const void*a, const void *b){return ((Node*)a)->price - ((Node*)b)->price; }void Init(int n)//并查集初始化 {for(int i = 0; i < n; i++){Rank[i] = 0;Uset[i] = i;} }int find(int x) {int root = x;while(root != Uset[root]) root = Uset[root];while(x != root){int t = Uset[x];Uset[x] = root;x = t;}return root; }void unionSet(int x, int y) {x = find(x);y = find(y);if(Rank[x] > Rank[y])Uset[y] = x;else {Uset[x] = y;if(Rank[x] == Rank[y]) Rank[y]++;} }int Kruskal(int n, int m) {int nEdge = 0, res = 0;qsort(edge, m, sizeof(edge[0]), cmp);//将边按照权值从小到大排序for(int i = 0; i < m && nEdge != n - 1; i++){if(find(edge[i].a) != find(edge[i].b))//判断当前这条边的两个端点是否属于同一棵树 {unionSet(edge[i].a, edge[i].b);res += edge[i].price;nEdge++;}}//如果加入边的数量小于m - 1,则表明该无向图不连通,等价于不存在最小生成树if(nEdge < n-1) res = -1;return res; } int main() {int n, m, ans;//n为村庄的数量,m为边的数量while(scanf("%d%d", &n, &m)&&n){Init(n);for(int i = 0; i < m; i++)scanf("%d%d%d", &edge[i].a, &edge[i].b, &edge[i].price);ans = Kruskal(n, m);if(ans == -1) printf("?\n");else printf("%d\n", ans);}return 0; }
View Code
另外,可以参考:http://blog.csdn.net/luomingjun12315/article/details/47700237
作者: AlvinZH
出处: http://www.cnblogs.com/AlvinZH/
本人Github:https://github.com/Pacsiy/JobDu
本文版权归作者AlvinZH和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载于:https://www.cnblogs.com/AlvinZH/p/6803711.html
最小生成树(Prim算法+Kruskal算法)相关推荐
- 最小生成树(Prim、Kruskal)算法,秒懂!
前言 在数据结构与算法的图论中,(生成)最小生成树算法是一种常用并且和生活贴切比较近的一种算法.但是可能很多人对概念不是很清楚,什么是最小生成树? 一个有 n 个结点的连通图的生成树是原图的极小连通子 ...
- 生成树的概念,最小生成树Prim算法 Kruskal算法
求解最小生成树可以用Prim算法 Kruskal算法
- 数据结构(六):图的概念、存储方式、基本操作、最小生成树、最短路径、有向无环图、关键路径 | Prim、Kruskal算法 | BFS、Dijkstra、Floyd算法 | 拓扑排序 | 求关键路径
文章目录 第六章 图 一.图 (一)图的定义 (二)图逻辑结构的应用 (三)无向图.有向图 (四)简单图.多重图 (五)顶点的度.入度.出度 (六)顶点-顶点的关系描述 (七)连通图.强连通图 (八) ...
- dijkstra算法_Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法
讲在前面的话,图的算法太多,理论知识肯定一篇文章讲不完,关于理论知识大家可以参考教材Sedgewick的<算法>或reference的链接,本文主要还是想在一篇文章中记录六种算法的Pyth ...
- 最小生成树原理及Kruskal算法的js实现
1. 生成树和最小生成树的概念 设图G(V,E)连通,则 生成树:包含图G(V,E)中的所有节点,及|V|-1条边的连通图,一个图的生成树可以有多颗 最小生成树:最小权重生成树,在生成树的概念上加一个 ...
- dfs时间复杂度_Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法
讲在前面的话,图的算法太多,理论知识肯定一篇文章讲不完,关于理论知识大家可以参考教材Sedgewick的<算法>或reference的链接,本文主要还是想在一篇文章中记录六种算法的Pyth ...
- Prim和Kruskal算法应用----城市水管连接
Prim和Kruskal算法应用----城市水管连接 问题描述: Description: 现在有n个城镇,编号为1, 2, 3, 4-n.他们之间有m条互通的道路,每条道路有相应的长度,现在基于这些 ...
- 【图解】Prim和Kruskal算法的区别
[贪心]Prim和Kruskal算法的区别 Kruskal算法和Prim算法的优劣 Kruskal算法,相较于Prim算法是基于点的操作,Kruskal算法是基于边的操作,思想也比Prim简单,更容易 ...
- 可视化最小生成树Prim、Kruskal
代码下载链接:(41条消息) 可视化最小生成树Kruskal,DEV配EGE-C文档类资源-CSDN文库 代码下载链接:(41条消息) 可视化最小生成树Prim,DEV配EGE-C文档类资源-CSDN ...
- 【数据结构】最小生成树 Prim算法 Kruskal算法
最小生成树应用场景: 假设以下场景,有一块木板,板上钉上一些钉子,这些钉子可以由一些细绳连接起来.假设每个钉子可以通过一根或者多根细绳连接起来,那么一定存在这样得情况,即用最少的细绳把所有的钉子连接起 ...
最新文章
- kvm虚拟化技术下虚拟机磁盘的数据保护
- 给你两个经纬度,计算他们之间的距离
- 修改xampp的mysql默认密码
- [crypto]-50-base64_encode和base64_decode的C语言实现
- 怎样才能到国外做博士后
- 计算机视觉与深度学习 | ORB特征提取:基于OpenCV+Python(附代码)
- asp python 定时任务_python定时任务最强框架APScheduler详细教程
- RPC调用和HTTP调用的区别你知道吗
- 查询linux服务器事物传输失败日志,查看fail2ban日志代替lastb查看登录失败记录
- sqlserver java odbc_Java JDBC------------------ODBC(SQLServer)链接
- Windows Phone 7 使用启动器(Lanucher)
- 【LaTeX】下载及安装步骤
- 麻省理工遍地走,6年经验安卓程序员面试微软,靠这份思维脑图拿下Offer!
- 内部收益率计算公式用计算机,内部收益率的计算公式是什么
- visio中图形任意位置添加连接点
- Internet Explorer之后的前端开发
- Python小项目-烤地瓜
- Mybatis注解开发笔记
- 淘宝/天猫按图搜索商品API接口,以图搜商品API接口,图片搜索API接口
- org.springframework.dao.InvalidDataAccessApiUsageException: ERR wrong number of arguments for ‘srem‘
热门文章
- Windows10下VB6.0开发——利用PictureBox控件实现数据点实时绘图
- 新的android包格式,在Android中注册新文件类型
- 计算机一级上网题怎么创建桌面快捷方式,计算机一级上机操作题2016
- 计算机关闭的时候自动更新,win7自动更新关闭有什么影响_win7系统关闭自动更新的步骤-win7之家...
- Jupyter Notebook 代码补全功能配置
- JavaScript学习——JavaScript 循环
- ThinkSNS Plus PHP开发概述
- Ansible之roles使用
- 1.13 单用户模式;1.14 救援模式;1.15 克隆虚拟机;1.16 Linux机器相互登录
- ES6:Rest 参数和参数默认值【转】