最小生成树是无向图中的一个问题,很常见。
在无向图中,连通而且不含有圈(环路)的图称为树。最小生成树(MST)的基本模型可以用下面的题目描述:

题目描述
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。

输入
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
当N为0时,输入结束,该用例不被处理。

输出
对每个测试用例,在1行里输出最小的公路总长度。

样例输入
8
1 2 42
1 3 68
1 4 35
1 5 1
1 6 70
1 7 25
1 8 79
2 3 59
2 4 63
2 5 65
2 6 6
2 7 46
2 8 82
3 4 28
3 5 62
3 6 92
3 7 96
3 8 43
4 5 28
4 6 37
4 7 92
4 8 5
5 6 3
5 7 54
5 8 93
6 7 83
6 8 22
7 8 17
0
样例输出
82

图的两个基本元素是点和边,与此对应,有两种方法可以构造最小生成树T。这两种算法都基于贪心法,因为MST问题满足贪心法的“最优性原理”,即全局最优包含局部最优。prim算法的原理是“最近的邻居一定在MST上”,kruskal算法的原理是“最短的边一定在MST上”。
(1)prim算法:对点进行贪心操作。从任意一个点u开始,把距离它最近的点v加入到T中;下一步,把距离{u,v}最近的点w加入到T中,继续这个过程,直到所有点都在T中。
(2)kruskal算法:对边进行贪心操作。从最短的边开始,把它加入到T中;在剩下的边中找最短的边,加入到T中;继续这个过程,直到所有点都在T中。
在这两个算法中,重要的问题是判断圈。最小生成树显然不应该有圈,否则就不是“最小”了。所以,在新加入一个点或者边的时候要同时判断是否形成了圈。

1、prim算法
设最小生成树的点的集合是U,开始时最小生成树为空,所以U为空。

(1)任取一点,例如点1,放到U中,U={1}。
(2)找离集合U中的点最近的邻居,即1的邻居,是2,放到U中,U={1,2}。
(3)找离U最近的点,是5,U={1,2,5}。
(4)距离U最近的点是5,但是它没有扩展新的点,不符合要求。
(5)加入4,U={1,2,5,4}。
(6)加入3,U={1,2,5,4,3}。所有的点都在U中,结束。
上面的步骤和Dijkstra算法的步骤非常相似,不同的是Dijkstra需要更新U的所有邻居到起点的距离,即“松弛”,而prim则不需要。所以,只需要把Dijkstra的程序简化一些即可。
和Dijkstra算法一样,prim程序也可以用优先队列来查找距离U最近的点,能优化算法。
prim的编程比较麻烦,kruskal更简单且高效。

2、kruskal算法
kruskal算法编程有以下两个关键技术:
(1)对边进行排序。可以用STL的sort()函数,排序后,依次把最短的边加入到T中。
(2)判断圈,即处理连通性问题。这个问题用并查集简单而高效,并查集是kruskal算法的绝配。
任意上面的图为例说明kruskal算法的操作步骤

(1)初始时最小生成树为空。令S是以节点i为元素的并查集,在开始时,每个点属于独立的集(为了便于讲解,下表中区分了结点i和集S,把集的编号加上可下划线):

(2)加入第一个短边(1-2):T={1-2}。在并查集S中,把结点2合并到结点1,也就是把结点2的集2改成结点1的集1。

(3)加入第二个短边(3-4),T={1-2,3-4}。在并查集S中,结点4合并到结点3.

(4)加入第三个最短边(2-5):T={1-2,3-4,2-5}。在并查集S中,把结点5合并到结点2,也就是把结点5的集5改成结点2的集1.在集1中,所有结点都指向了根结点,这样可以避免并查集的长链问题。

(5)第四个最短边(1-5)。检查并查集S,发现5已经属于集1,丢弃这个边。这一步实际上是发现了一个圈。并查集的作用就体现在这里。
(6)加入第五个最短边(2-4)。在并查集S中,把结点4的集并到结点2的集。注意这里结点4的集原本为3,实际上的修改是把结点3的集3改成1。
(7)重复以上操作,直到结束。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int NUM=105;
int S[NUM];//并查集
struct Edge{int u,v,w;}edge[NUM*NUM];
bool cmp(Edge a,Edge b){return a.w<b.w;};
int find(int u){return S[u]==u?u:find(S[u]);}
int n,m;
int kruskal(){int ans=0;for(int i=1;i<=n;++i)S[i]=i;sort(edge+1,edge+m+1,cmp);for(int i=1;i<=m;++i){int b=find(edge[i].u);int c=find(edge[i].v);if(b==c)continue;//产生了圈,丢弃这个边S[c]=b;//合并ans+=edge[i].w;//计算MST}return ans;
}
int main(){while(~scanf("%d",&n)){if(!n)return 0;m=n*(n-1)/2;for(int i=1;i<=m;++i)scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);printf("%d\n",kruskal());}
}

算法学习:最小生成树相关推荐

  1. matlab中x从0到5不含0,关于MATLAB的数学建模算法学习笔记

    关于MATLAB的数学建模算法学习笔记 目录 线性规划中应用: (3) 非线性规划: (3) 指派问题;投资问题:(0-1问题) (3) 1)应用fmincon命令语句 (3) 2)应用指令函数:bi ...

  2. 两个字符串的最长公共子序列长度_算法学习笔记(58): 最长公共子序列

    (为什么都更了这么多篇笔记了,这时候才讲这么基础的内容呢?因为我本来以为LCS这种简单的DP不用讲的,结果CF不久前考了LCS的变式,然后我发现由于自己对LCS一点都不熟,居然写不出来 ,于是决定还是 ...

  3. Python最优化算法学习笔记(Gurobi)

    微信公众号:数学建模与人工智能 github地址:https://github.com/QInzhengk/Math-Model-and-Machine-Learning Python最优化算法学习笔 ...

  4. 基础算法学习大纲(附加yxc大佬算法模板)

    基础算法学习大纲总结 学习算法路线 1.基础算法 模板 1.排序 2.二分 3.高精度 4.前缀和与差分 5.双指针算法 6.位运算 7.离散化 8.区间合并 2.数据结构 模板 1.链表与邻接链表( ...

  5. 计算机专业考研复试上机算法学习

    计算机专业考研复试上机算法学习 这篇博客是博主在准备可能到来的线下上机复试基于王道机试指南的学习,将各道习题链接和代码记录下来,这篇博客权且当个记录. 文章目录 计算机专业考研复试上机算法学习 1.S ...

  6. 数据结构与算法学习⑤(BFS和DFS 贪心算法 二分查找)

    数据结构与算法学习⑤ 数据结构与算法学习⑤ 1.BFS和DFS 1.1.深度优先搜索算法 1.2.广度优先搜索算法 面试实战 102. 二叉树的层序遍历 104. 二叉树的最大深度 515. 在每个树 ...

  7. 数学建模图论算法学习总结

    数学建模图论算法学习总结 图论基本知识 B站视频: https://www.bilibili.com/video/av18374161/?p=35 https://www.bilibili.com/v ...

  8. 数据结构与算法学习④(哈夫曼树 图 分治回溯和递归)

    数据结构与算法学习④(哈夫曼树 图 回溯和递归 数据结构与算法学习④ 1.哈夫曼树 1.1.相关概念 1.2.哈夫曼树的构建 1.3.哈夫曼编码 1.4.面试题 2.图 2.1.图的相关概念 2.2. ...

  9. R-CNN算法学习(步骤一:候选区域生成)

    R-CNN算法学习(步骤一:候选区域生成) 论文链接:https://arxiv.org/abs/1311.2524 源码链接:https://github.com/rbgirshick/rcnn 算 ...

  10. 算法学习笔记22:贪心算法

    目录 贪心算法:如何用贪心算法实现Huffman压缩编码 如何理解"贪心算法" 贪心算法实战分析 1.分糖果 2. 钱币找零 3. 区间覆盖 解答开篇 内容小结 贪心算法:如何用贪 ...

最新文章

  1. 【数学专题】 筛质数、分解质因数和快速幂
  2. Xamarin Anroid App访问网站失败
  3. java builder pool_每周10道Java面试题:String, String Pool, StringBuilder
  4. PyQt5 QTableView 全部item居中
  5. java input 数组_请问如何input一个数组?
  6. AC-WEB使用HTTPS登录
  7. mysql服务启动成功后卸载_安装,启动与卸载Mysql系统服务(MYSQL常见问题)
  8. 今天有人问,为何汝粉丝这么少?
  9. UTM(Undergraduate Texts in Mathematics)书单 |附下载链接
  10. C语言的风花雪夜(C语言下雪动画)
  11. 丹佛机场行李系统案例分析
  12. Swift光学识别中国二代居民身份证
  13. 记一次npm install 报RequestError: connect ETIMEDOUT 20.205.243.166:443和RequestError: socket hang up
  14. 拿好这份踏青攻略,智慧出游领略大好河山!
  15. 引力波,你果真懂了吗?
  16. win10出现错误代码0x80073712的解决办法
  17. Win11 “qq无法访问个人文件夹”解决方法(原创)
  18. 网页中引入网易云音乐,贴边隐藏
  19. java逻辑值_java、 若x = 5,y = 10,则x y和x = y的逻辑值分别为 和 。...
  20. 圣思园java.doc_Java Web学习历程-(基于圣思园视频教程)

热门文章

  1. Live Mesh - Synchronizing life
  2. Delphi 项目版本
  3. Android开发指南(39) —— Testing Fundamentals
  4. 用Java实现向Cassandra数据库中插入和查询数据
  5. OneProxy中间件生产使用经验视频分享
  6. Oracle EBS-SQL (PO-10):检查过期采购未接收订单.sql
  7. 微软云计算解决方案与下一代数据中心
  8. RAID 的各种方案
  9. 如何记才能不搞混绝对路径和相对路径
  10. error: Unexpected trailing comma (comma-dangle) at src\components\Login.vue:99:4: