公式如果有滚动条影响阅读的话,右键公式>Math Settings>Math Renderer>SVG即可。


最小生成树及两个算法的简介

生成树即在一张图上找到连接所有顶点的一棵树,显然如果点数为$n$,这棵生成树的边数就是$n-1$。

最小生成树(Minimum Spanning Tree)就是这张图上边权之和最小的生成树。

常用的两个最小生成树算法有两个:Kruskal和Prim。两个算法都是基于贪心的思想,理解起来也十分简单,下面把边权具象为边的长度来理解。

Kruskal算法的思想是:将所有边长度从小到大排序,依次遍历,如果加入这条边不会形成环,就直接加入。当边数$=$点数$-1$时,完成最小生成树。

(该算法因需要判断成环,所以需要并查集的参与,如果不会可以去搜索更多信息)

Prim算法的思想是:随便选一个点开始,向周围找一个距离最近的点,形成一个整体,接着找这个整体与周围距离最近的点,加入这个整体,重复上述步骤直到所有点被加入。

推荐参考此视频,下面的代码与视频内容较为贴合,结合理解更好(特别是Prim算法的一堆数组)。

代码

Kruskal

 1 #include<iostream>
2 #include<queue>
3 #include<algorithm>
4 #define MAXN 1010
5 #define MAXM 1010
6 using namespace std;
7 struct edge{
8 int u,v,w;
9 }edges[MAXM];
10 bool cmp(edge a,edge b){
11 return a.w<b.w;
12 }
13 int n,m,fa[MAXN],sum;
14 int find(int x){
15 if(fa[x]==x) return x;
16 return fa[x]=find(fa[x]);
17 }
18 queue<int> path;
19 int main(){
20 cin>>n>>m;
21 for(int i=0;i<m;i++){
22 cin>>edges[i].u>>edges[i].v>>edges[i].w;
23 }
24 for(int i=0;i<n;i++) fa[i]=i;
25 sort(edges,edges+m,cmp);
26 int cnt=0;
27 for(int i=0;i<m;i++){
28 int u=find(edges[i].u),v=find(edges[i].v);
29 if(u==v) continue;
30 fa[u]=v;
31 cnt++;
32 sum+=edges[i].w;
33 path.push(i);
34 if(cnt>=n-1) break;
35 }
36 cout<<sum<<"\n";
37 //记录边来存图,所以此处只输出边的编号
38 while(!path.empty()){
39 cout<<path.front()<<" ";
40 path.pop();
41 }
42 return 0;
43 }

Prim

 1 #include<iostream>
2 #include<cstring>
3 #define MAXN 1010
4 using namespace std;
5 int map[MAXN][MAXN],mindist[MAXN],parent[MAXN];
6 bool selected[MAXN];
7 int n,m,sum;
8 int main(){
9 memset(mindist,127,sizeof mindist);//INF
10 int maxx=mindist[0];
11 cin>>n>>m;
12 for(int i=0;i<m;i++){
13 int u,v,w;
14 cin>>u>>v>>w;
15 map[u][v]=map[v][u]=w;
16 }
17 int current=0;
18 for(int i=0;i<n-1;i++){
19 selected[current]=1;//1.Update
20 for(int j=0;j<n;j++){
21 if(!selected[j]&&map[current][j]){
22 if(map[current][j]<mindist[j]){
23 mindist[j]=map[current][j],parent[j]=current;
24 }
25 }
26 }
27 int minn=maxx,minpos=-1;//2.Scan
28 for(int j=0;j<n;j++){
29 if(!selected[j]&&mindist[j]<minn){
30 minn=mindist[j],minpos=j;
31 }
32 }
33 sum+=minn,current=minpos;//3.Add
34 }
35 cout<<sum<<endl;
36 //用了邻接矩阵存,所以此处只输出节点编号
37 for(int i=1;i<n;i++){
38 cout<<i<<" => "<<parent[i]<<"\n";
39 }
40 return 0;
41 }

附视频中的图例

Input:
9 14
0 1 4
0 7 8
1 7 11
1 2 8
7 8 7
6 7 1
2 8 2
6 8 6
2 5 4
5 6 2
2 3 7
3 5 14
3 4 9
4 5 10
Output:
37

View Sample

比较

我们可以发现,Prim算法每次都要遍历一遍所有点,找出与已确定区间相连的边,无论两点之间有无边,我们都需要每轮遍历一次。所以Prim算法的时间复杂度是$O(n^2)$,适用于点少边多的图(稠密图),存储方式也一般使用邻接矩阵;

而Kruskal算法与点无关,整个过程就是按边的权值排序,依次选择,所以与点的数量无关。故时间复杂度是$O(mlogm)$,适用于点多边少的图(稀疏图)。存图只需要把边记录下来即可,不过需要用并查集维护一下点。

[笔记]Kruskal和Prim算法的比较的更多相关文章

  1. 最小生成树——Kruskal与Prim算法

    最小生成树——Kruskal与Prim算法 序: 首先: 啥是最小生成树??? 咳咳... 如图: 在一个有n个点的无向连通图中,选取n-1条边使得这个图变成一棵树.这就叫“生成树”.(如下图) 每个 ...

  2. Kruskal和Prim算法求最小生成树

    Kruskal算法求最小生成树 测试数据: 5 6 0 1 5 0 2 3 1 2 4 2 4 2 2 3 1 1 4 1 输出: 2 3 1 1 4 1 2 4 2 0 2 3 思路:在保证不产生回 ...

  3. 最小生成树(Kruskal和Prim算法)

    关于图的几个概念定义:          关于图的几个概念定义: 连通图:在无向图中,若任意两个顶点vi与vj都有路径相通,则称该无向图为连通图. 强连通图:在有向图中,若任意两个顶点vi与vj都有路 ...

  4. 最小生成树的kruskal、prim算法

    kruskal算法和prim算法 都说 kruskal是加边法,prim是加点法 这篇解释也不错:这篇 1.kruskal算法 因为是加边法,所以这个方法比较合适稀疏图.要码这个需要先懂并查集.因为我 ...

  5. 1.1.2最小生成树(Kruskal和Prim算法)

    部分内容摘自 勿在浮沙筑高台 http://blog.csdn.net/luoshixian099/article/details/51908175 关于图的几个概念定义: 连通图:在无向图中,若任意 ...

  6. 算法导论--最小生成树(Kruskal和Prim算法)

    转载出处:勿在浮沙筑高台http://blog.csdn.net/luoshixian099/article/details/51908175 关于图的几个概念定义: 连通图:在无向图中,若任意两个顶 ...

  7. [讲解]prim算法<最小生成树>

    最小生成树的方法一般比较常用的就是kruskal和prim算法 一个是按边从小到大加,一个是按点从小到大加,两个方法都是比较常用的,都不是很难... kruskal算法在本文里我就不讲了,本文的重点是 ...

  8. 关于最小生成树 Kruskal 和 Prim 的简述(图论)

    模版题为[poj 1287]Networking. 题意我就不说了,我就想简单讲一下Kruskal和Prim算法.卡Kruskal的题似乎几乎为0.(●-`o´-)ノ 假设有一个N个点的连通图,有M条 ...

  9. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  10. 贪心算法-最小生成树Kruskal算法和Prim算法

    Kruskal算法: 不断地选择未被选中的边中权重最轻且不会形成环的一条. 简单的理解: 不停地循环,每一次都寻找两个顶点,这两个顶点不在同一个真子集里,且边上的权值最小. 把找到的这两个顶点联合起来 ...

随机推荐

  1. 【中文】【吴恩达课后编程作业】Course 4 - 卷积神经网络 - 第三周作业

    [中文][吴恩达课后编程作业]Course 4 - 卷积神经网络 - 第三周作业 - 车辆识别 上一篇:[课程4 - 第三周测验]※※※※※ [回到目录]※※※※※下一篇:[课程4 - 第四周测验] ...

  2. ChatMoney化身恋爱大师来帮助你收获完美爱情!

    本文由 ChatMoney团队出品 介绍说明 在纷繁复杂的情感世界里,寻找真爱的道路常常充满迷茫和困惑.但现在,有了 AI 智能体恋爱大师,为您的爱情之旅点亮明灯. AI 智能体恋爱大师并非传统意义上 ...

  3. java的StackOverflowError异常

    之前明明能查到,现在突然报错StackOverflowError,并一直在控制台返回空对象 多次遇到这种情况 发现是东西存入缓存中,缓存内存不够导致栈溢出,刷新kill缓存即可

  4. ARCHIV_CREATE_FILE 员工头像上传

    *&---------------------------------------------------------------------* *& Report ZHRR_011 ...

  5. 使用Spread控件构建Checkbook工程的技术指南

    引言 在现代Web应用开发中,电子表格控件已成为处理财务数据.报表展示等场景的重要工具.葡萄城的Spread控件作为一款功能强大的ASP.NET表格组件,为开发者提供了丰富的API和灵活的定制能力.本 ...

  6. AI应用实战课学习总结(1)必备AI基础理论

    大家好,我是Edison. 由于公司的愿景逐渐调整为ONE Tech Company,公司的IT战略也逐渐地朝着Data & AI Driven发展,因此近半年来我一直在学习大模型相关的东西, ...

  7. 如何获取上次BIOS所用时间

    在Windows任务管理器的"启动应用"页签的右上角,有一个"上次BIOS所用时间",这个时间可以通过注册表项来获取,注册表位置如下 HKLM\SYSTEM\C ...

  8. C# Winform 下 DataGridView 行(SelectedRows)转 模型 Model

    /// <summary> /// DataRow 转 Model /// </summary> /// <typeparam name="T"> ...

  9. SQL Server 清除表TRUNCATE TABLE 提示: 因为该表正由 FOREIGN KEY 约束引用

    https://blog.csdn.net/dengguawei0519/article/details/101315699 1.找到引用这个表外键名称 SELECT * FROM sys.forei ...

  10. 【6】树形DP学习笔记

    前言 教练说过,树形 DP 是一个抽象的东西,很多状态比较难以理解,后面具体的学习方法,忘了. UPD on \(2024.11.21\):修复了例题 \(5\) 的假做法和假代码. 普通树形 DP ...