文章目录

  • Prim算法
  • Kruskal算法

主要内容:

Prim算法

最小生成树对应的问题一般都是无向图,最小生成树所构成的图总边权之和最小,但不能是环,否则不能称之为"最小"。

Prim算法是求解最小生成树的算法之一,适用于稠密图,Prim算法和Dijkstra算法步骤很相似,不同的是Dijkstra需要更新所有邻居到起点的距离,也就是"松弛操作",但Prim不需要,只需要把距离集合最近的点加入集合中去。

prim算法步骤:

设最小生成树中点的集合为U.
① 任取一点,加入集合,例如点1

② 找距离集合U中的点最近的邻居,也就是1的邻居,很明显是2,把2加入集合

③ 继续找距离U最近的点,是5

④ 由于1 ~ 5这条边是集合内部两个点连接而成,没有扩展新的点(形成了环),操作不会执行。

⑤那最近的就是4号点了,距离集合最近的点是4,加入。

⑥ 加入3,得到最终的集合,组成的就是最小生成树。

代码思路:

  1. 初始化距离为无穷大
  2. 找到集合外距离最近的点赋给 t
  3. 用 t 更新其它点到集合的距离
  4. st[t] = true(把t加到集合中去)

代码模板:

//稠密图用邻接矩阵存储
int prim()
{memset(dist, 0x3f, sizeof dist);int res = 0;  //权重之和for(int i = 0; i < n; i ++ )//n次迭代{int t = -1;for(int j = 1; j <= n;j ++ ){if(!st[j] && (t == -1 || dist[t] > dist[j]))t = j;//t存储当前距离最小的点}if(i && dist[t] == INF) return INF;//图不连通else if(i) res += dist[t];  //先累加再更新st[t] = true;for(int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]);//与Dijkstra的不同之处}return res;
}

例题:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 510, INF = 0x3f3f3f3f;
int n, m;
int g[N][N];
int dist[N];
bool st[N];
int prim()
{memset(dist, 0x3f, sizeof dist);int res = 0;for(int i = 0; i < n; i ++ ){int t = -1;for(int j = 1; j <= n;j ++ ){if(!st[j] && (t == -1 || dist[t] > dist[j]))t = j;}if(i && dist[t] == INF) return INF;else if(i) res += dist[t]; st[t] = true;for(int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]);}return res;
}
int main()
{cin >> n >> m;memset(g, 0x3f, sizeof g);while(m -- ){int a, b, c;cin >> a >> b >> c;g[a][b] = g[b][a] = min(g[a][b], c);}int t = prim();if(t == INF) cout << "impossible" << endl;else cout << t << endl;return 0;
}

对于稀疏图,可以使用堆优化版的prim算法,但这种算法不常用,用kruskal算法效率就很高。


Kruskal算法

kruskal算法的两个关键:

  1. 对边进行排序。使用sort()排序,依次把最短边加入最小生成树中,这就是为什么适用于稀疏图的原因。
  2. 判断环,也就是处理连通性问题,使用并查集简单高效,是kruskal的、算法的绝配。

关于并查集查看:并查集

kruskal过程分析:
①初始最小生成树为空

②加入第一个最短边,把2并入集合1中,构成以点1为根结点的树

③继续找最短边,这时候把4并入集合3中

④继续查找,5并入集合1,继续查找,发现5已经在集合1中,也就是形成一个环,放弃合并。

⑤ 将4并入集合1,但4已经并入集合3,所以将集3并入集1,形成最小生成树。

代码:


int kru()
{sort(e, e + m);//将边升序排序for(int i = 1; i <= n; i ++) p[i] = i;//初始化并查集int res = 0, cnt = 0;//res边权和,cnt为加入最小生成树的边数for(int i = 0; i < m ; i++ )//遍历边{int a = e[i].a, b = e[i].b, w = e[i].w;a = find(a), b = find(b);if(a != b)//a,b不在同一集合内{p[a] = b;//合并res += w;//累加cnt ++ ;}}if(cnt < n - 1) return INF;//加入边数小于n - 1说明不连通return res;
}

例题:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N  = 100010, M = 200010, INF = 0x3f3f3f3f;
int p[N];
int n, m;
struct Edge{int a, b, w;//结构体内嵌比较函数bool operator < (const Edge &W) const {return w < W.w;}
}e[M];int find(int x)
{if(x != p[x]) p[x] = find(p[x]);return p[x];
}int kru()
{sort(e, e + m);for(int i = 1; i <= n; i ++) p[i] = i;int res = 0, cnt = 0;for(int i = 0; i < m ; i++ ){int a = e[i].a, b = e[i].b, w = e[i].w;a = find(a), b = find(b);if(a != b){p[a] = b;res += w;cnt ++ ;}}if(cnt < n - 1) return INF;return res;}
int main()
{cin >> n >> m;for(int i = 0; i < m; i ++ )    {int a, b, c;cin >> a >> b >> c;e[i] = {a, b ,c};}int t = kru();if(t == INF) puts("impossible");else cout << t << endl;return 0;
}

复杂度分析:
遍历边时是O(m)
对边排序时复杂度O(mlogm),整个算法中用时最长的一步。复杂度不超过O(mlogm).

Prim算法、Kruskal算法相关推荐

  1. 生成树的概念,最小生成树Prim算法 Kruskal算法

    求解最小生成树可以用Prim算法 Kruskal算法

  2. 最小生成树(Prim、Kruskal)算法,秒懂!

    前言 在数据结构与算法的图论中,(生成)最小生成树算法是一种常用并且和生活贴切比较近的一种算法.但是可能很多人对概念不是很清楚,什么是最小生成树? 一个有 n 个结点的连通图的生成树是原图的极小连通子 ...

  3. dijkstra算法_Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法

    讲在前面的话,图的算法太多,理论知识肯定一篇文章讲不完,关于理论知识大家可以参考教材Sedgewick的<算法>或reference的链接,本文主要还是想在一篇文章中记录六种算法的Pyth ...

  4. dfs时间复杂度_Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法

    讲在前面的话,图的算法太多,理论知识肯定一篇文章讲不完,关于理论知识大家可以参考教材Sedgewick的<算法>或reference的链接,本文主要还是想在一篇文章中记录六种算法的Pyth ...

  5. 数据结构(六):图的概念、存储方式、基本操作、最小生成树、最短路径、有向无环图、关键路径 | Prim、Kruskal算法 | BFS、Dijkstra、Floyd算法 | 拓扑排序 | 求关键路径

    文章目录 第六章 图 一.图 (一)图的定义 (二)图逻辑结构的应用 (三)无向图.有向图 (四)简单图.多重图 (五)顶点的度.入度.出度 (六)顶点-顶点的关系描述 (七)连通图.强连通图 (八) ...

  6. Prim和Kruskal算法应用----城市水管连接

    Prim和Kruskal算法应用----城市水管连接 问题描述: Description: 现在有n个城镇,编号为1, 2, 3, 4-n.他们之间有m条互通的道路,每条道路有相应的长度,现在基于这些 ...

  7. 【图解】Prim和Kruskal算法的区别

    [贪心]Prim和Kruskal算法的区别 Kruskal算法和Prim算法的优劣 Kruskal算法,相较于Prim算法是基于点的操作,Kruskal算法是基于边的操作,思想也比Prim简单,更容易 ...

  8. 基本数据结构(图: 基本结构,DFS,prim算法, kruskal算法)

    #include <iostream> using namespace std; //约定: //1. 图是由很多节点(VERTEX)构成的, 因此图结构是由一个VERTEX的链表构成的, ...

  9. 【数据结构】最小生成树 Prim算法 Kruskal算法

    最小生成树应用场景: 假设以下场景,有一块木板,板上钉上一些钉子,这些钉子可以由一些细绳连接起来.假设每个钉子可以通过一根或者多根细绳连接起来,那么一定存在这样得情况,即用最少的细绳把所有的钉子连接起 ...

  10. hdu 1233 还是畅通工程 最小生成树(prim算法 + kruskal算法)

    还是畅通工程                                                                            Time Limit: 4000/2 ...

最新文章

  1. 快应用 - 应用签名校验失败
  2. atitit.ajax bp dwr 3.的注解方式配置使用流程总结.....
  3. rtmp 推送h264 + aac 的数据
  4. 【PAG组件】-从解码渲染层面对比 PAG 与 lottie
  5. Theano 中文文档 0.9 - 7.1.1 Python教程
  6. 已知: 每个飞机只有一个油箱, 飞机之间可以相互加油(注意是相互,没有加油机) 一箱油可供一架飞机绕地球飞半圈,问题:为使至少一架飞机绕地球一圈回到起飞时的飞机...
  7. Android应用程序版本号管理(官方文档中文版) 2011-08-07 22:03:36
  8. wordpress中如何正确书写robots.txt
  9. Kettle下载安装使用
  10. VS2005制作安装包
  11. Preparing Your Data for Use with robot_localization 准备 robot_localization 数据
  12. 固态硅压阻压力传感器的优点
  13. 3000个最常用的英语单词
  14. MIPI 系列之 DSI
  15. 步进电机 高速光耦_高速光耦有哪些_高速光耦如何选型 - 全文
  16. matlab 怎么求直线斜率,matlab中如何求近似(不平滑)直线的斜率
  17. 三个小孩去饭店点菜用计算机算钱,去饭店别点这三个菜!点菜“潜规则”你该知道(组图)...
  18. PyScripter的下载
  19. 使用画图工具draw.io的嵌入模式实现uml图绘制功能的尝试(1)
  20. (HEM/OHEM)hard negative(example)mining难例挖掘 与focal loss、GHM损失函数

热门文章

  1. 零件加工 贪心 题解
  2. ldd显示可执行模块的dependenc
  3. 309. Best Time to Buy and Sell Stock with Cooldown**
  4. 终点条件下的轨迹预测:It is not the Journey but the Destination: Endpoint Conditioned Trajectory Prediction
  5. 数学建模之规划1——线性规划
  6. c语言课程设计报告停车系统,停车场管理系统C语言课程设计
  7. python io模块
  8. 物联网技术概论:第7章
  9. PTA新浪微博热门话题(题面毒瘤)
  10. 基于EasyNVR实现RTSP_Onvif监控摄像头Web无插件化直播监控之视频直播网络占用率大如何解决的问题分析