最小生成树超详细介绍

目录

一.最小生成树的介绍

1.最小生成树的简介

2.最小生成树的应用

3.最小生成树的得出方法

二.Kruskal算法

1.基本思想:

2.步骤:

3.实现细节:

4.样例分析:

5.Kruskal算法代码实现:

三.Prim算法

1.基本思想:

2.步骤:

3.实现细节:

4.样例分析:

5.Prim算法代码实现

四.总结


一.最小生成树的介绍

1.最小生成树的简介

最小生成树(Minimum Spanning Tree,简称MST,在一个连通的无向图,最小生成树是指包含图中所有顶点的一棵树,且该树的所有边的权重之和最小,关键在于最小两个关键。

在上面的示例图中我们知道了生成的数是不能有闭环的,那么我们怎么去理解最小的意思。

其实在每个点之间相连接的边中是有边的长度的,如下:

我们需要找出的边构成生成树,并且包含图中的所有顶点,使得边的权重之和最小。

2.最小生成树的应用

那么我们很好奇,我们为什么要去寻找这么一个最小生成树呢?

设想,面对一个交通落后的城市

在当今经济发展迅速的阶段,国家肯定不允许城市之间没有一条公路将各个城市串通起来,但是也不会盲目乱铺设,因为人力和成本是很多的,那么串通每个城市之间的公路就是边,我们利用最小生成树将这些城市串通起来的同时,也减少了成本的浪费,这个就是最小生成树的应用之一。

最小生成树在现实应用中具有广泛的用途。一主要应用领域是网络设计,例如通信网络和计算机网络的规划。通过选择最小生成树,可以确保网络中的节点连接最优,减少通信成本。在城市规划中,最小生成树被用于设计交通网络,确保道路布局经济高效。电力系统规划也借助最小生成树,以建立最优的电力输送网络。此外,在电路板设计、社交网络分析以及物流规划等领域,最小生成树都能提供有效的解决方案,降低资源消耗,提高系统效率。这些应用反映了最小生成树作为一种优化工具在解决各种连接和布线问题上的重要性。

3.最小生成树的得出方法

找出最小生成树有这么两个方法。

Kruskal算法和Prim算法。

虽然是两个方法,但是都有使用了贪心的思想。

下面将对两个方法进行详介。

二.Kruskal算法

1.基本思想:

  • 将图中所有的边按照权值从小到大排序。
  • 从小到大遍历排序后的边,如果边的两个端点不在同一个连通分量中,则将这条边加入最小生成树中,并将这两个端点合并为一个连通分量。(也就是新加的边不能与其他边构成环)

2.步骤:

  • 对图中所有边按照权值进行排序。
  • 初始化一个空的最小生成树。
  • 依次考察排序后的边,如果加入某条边不形成环,则将其加入最小生成树中。

3.实现细节:

  • 使用并查集(Disjoint Set)来管理连通分量。
  • 可以通过贪心的思想逐步加入边,直到所有顶点都在同一连通分量中为止。(也就是加入的边等于所有的顶点-1)

4.样例分析:

我们以这个图为例:

1.先将边按照从小到大分好

2.初始一个空的最小生成树

3.慢慢从小到大填入边

当我们连接4--6时,此时闭成一个环,用红色代表这条边不加入。

此时加入的边为顶点数(7)-1,所以代表已经全部串通,所以最小生成树的边之和就是:

1+2+2+3+4+4=16

5.Kruskal算法代码实现:

首先可以建立一个结构体,里面放上边联通的两个节点和边的长度。

struct node{int x,y,w;
}a[1000];

因为Kruskal算法需要使用到并查集,所以下面是必不可少的Find函数。

int Find(int x)
{if(pre[x]==x) return x;return pre[x]=Find(pre[x]);
}

由于需要排序,我们这里直接使用c++的sort函数,加上自定义函数cmp

bool cmp(node &x,node &y)
{return x.w<y.w;
}

这样就构成了我们的核心函数Kruskal函数。

void Kruskal()
{sort(a+1,a+1+m,cmp);for(int i=1;i<=m;i++){int fx=Find(a[i].x);int fy=Find(a[i].y);if(fx==fy) continue;pre[fx]=fy;ans+=a[i].w;cnt++;if(cnt==n-1)break; }
}

得到完整代码:

#include<bits/stdc++.h>
using namespace std;
struct node{int x,y,w;
}a[1000];
int n,m,ans=0,cnt=0;
int pre[1000];
int Find(int x)
{if(pre[x]==x) return x;return pre[x]=Find(pre[x]);
}
bool cmp(node &x,node &y)
{return x.w<y.w;
}
void Kruskal()
{sort(a+1,a+1+m,cmp);for(int i=1;i<=m;i++){int fx=Find(a[i].x);int fy=Find(a[i].y);if(fx==fy) continue;//如果在一个集合就跳过 pre[fx]=fy;ans+=a[i].w;cnt++;if(cnt==n-1)//当加入的边等于顶点数-1,就停止循环 break; }
}
int main()
{cin>>n>>m;for(int i=1;i<=n;i++){pre[i]=i;//初始化 }for(int i=1;i<=m;i++){cin>>a[i].x>>a[i].y>>a[i].w;}Kruskal();//进入核心代码 if(cnt==n-1)cout<<ans<<endl;//可以得到答案,直接输出 else cout<<-1<<endl;//不可以接通 return 0;
}

我们输出来试试看,是不是得到答案16。

三.Prim算法

1.基本思想:

  • 选择一个起始顶点,然后逐步选择与当前生成树相邻的权值最小的边,并将连接的顶点加入生成树。
  • 重复以上步骤,直到生成树包含图中的所有顶点。

2.步骤:

  • 从任意顶点开始,初始化一个空的最小生成树。
  • 选择一个与当前生成树相邻的边中权值最小的边,将其连接的顶点加入最小生成树。
  • 重复上述步骤,直到最小生成树包含了所有顶点。

3.实现细节:

  • 使用优先队列(最小堆)来维护当前生成树与其余顶点之间的边。
  • 根据贪心策略,每次选择权值最小的边。

4.样例分析:

还是以这个图为例子

以0这个节点出发,我们有四条边可以加入。

我们选择这最小的。

然后从0和2这两个点出发,继续寻找,发现有两个2,我们选其中一个就行。

按照这种规则下去,我们得到了最小生成树,红色边是由于构成了闭环而没有使用的边,,绿色为使用的边。

我们来计算一下使用到的所有边的长度:

1+2+2+3+4+4=16。

我们发现这个就是我们前得到的答案。

5.Prim算法代码实现

首先生成最小堆。

struct node
{int u, w; // u是节点,w是花费bool operator < (node x) const{return w > x.w;} //重载运算符,生成最小堆
};

将每个顶点初始化为无穷大

	for(int i = 0; i < n; i++)dis[i] = INF; // 初始化dis[]

加边函数

void add(int u, int v, int w)
{a[++num].to = v;a[num].w = w;a[num].next = head[u];head[u] = num;
} // 加边

得到完整代码:

#include<bits/stdc++.h>
using namespace std;
const int INF = 1e9;
struct data
{int to, next, w;
} a[400002]; //链式前向星
struct node
{int u, w; // u是节点,w是花费bool operator < (node x) const{return w > x.w;} //重载运算符,生成最小堆
};
int dis[200010], head[200010], num;// dis是最小花费,head存边,num为边数
bool vis[200010];
int n, m, ans = 0, cnt = 0;
void add(int u, int v, int w)
{a[++num].to = v;a[num].w = w;a[num].next = head[u];head[u] = num;
} // 加边
priority_queue<node> q;
void Prim()
{q.push((node) {0, 0});while(!q.empty()||cnt < n) // 进行n-1次 {node x = q.top();q.pop();if(vis[x.u]) continue;vis[x.u] = true;cnt++;ans += x.w;for(int i = head[x.u]; i ; i = a[i].next) if(a[i].w < dis[a[i].to]) {dis[a[i].to] = a[i].w;q.push((node) {a[i].to, a[i].w});}}
}
int main()
{cin>>n>>m;for(int i = 1; i <= m; i++){int u, v, w;cin>>u>>v>>w;add(u, v, w); add(v, u, w); // 需要加两次无向图 }for(int i = 0; i < n; i++)dis[i] = INF; // 初始化dis[]Prim();if(cnt==n)cout<<ans<<endl; else cout<<"-1"<<endl; return 0;
}

我们输出一下试试。

代码得到正确答案。

四.总结

  • Kruskal更适合稀疏图,因为它按照边的权值排序,而不考虑顶点的度。
  • Prim更适合稠密图,因为它按照顶点的度增长来选择边,每次选择与当前生成树相邻的最小权值边。
  • Kruskal的时间复杂度主要取决于对边进行排序的时间,通常为O(E log E)
  • Prim的时间复杂度通常为O(E log V)。

里面的E为边的数量,V为顶点的数量。

 是不是已经完美掌握了。

赶紧去练练题目,来巩固一下知识。

P3366 【模板】最小生成树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P1194 买礼物 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)


最小生成树就介绍到这里。

本篇完~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/670685.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【多模态大模型】视觉大模型SAM:如何使模型能够处理任意图像的分割任务?

SAM&#xff1a;如何使模型能够处理任意图像的分割任务&#xff1f; 核心思想起始问题: 如何使模型能够处理任意图像的分割任务&#xff1f;5why分析5so分析 总结子问题1: 如何编码输入图像以适应分割任务&#xff1f;子问题2: 如何处理各种形式的分割提示&#xff1f;子问题3:…

【数据结构和算法】--- 基于c语言排序算法的实现(1)

目录 一、排序的概念及其应用1.1排序的概念1.2 排序的应用1.3 常见的排序算法 二、插入排序2.1直接插入排序2.2 希尔排序2.2.1 预排序2.2.2 缩小gap2.2.3 小结 三、选择排序3.1 直接选择排序3.2 堆排序 一、排序的概念及其应用 1.1排序的概念 排序&#xff1a; 所谓排序&…

RTE2023第九届实时互联网大会:揭秘未来互联网趋势,PPT分享引领行业新思考

随着互联网的不断发展&#xff0c;实时互动技术正逐渐成为新时代的核心驱动力。 在这样的背景下&#xff0c;RTE2023第九届实时互联网大会如期而至&#xff0c;为业界人士提供了一个探讨实时互联网技术、交流创新理念的绝佳平台。 本文将从大会内容、PPT分享价值等方面&#…

ShardingSphere 5.x 系列【6】YAML 配置介绍

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 前言2. YamlConfiguration3. 常用配置项3.1 JDBC 驱动3.2 数据源3.3 规则…

mysq开启慢查询日志,对慢查询进行优化

1.创建实验的环境 创建对应的数据库&#xff0c;然后写脚本向数据库中写入400万条的数据 //创建实验用的数据库 CREATE DATABASE jsschool;//使用当前数据库 USE jsschool;//创建学生表 CREATE TABLE student (sno VARCHAR(20) PRIMARY KEY COMMENT 学生编号,sname VARCHAR(20…

加固平板电脑丨三防智能平板丨工业加固平板丨智能城市管理

随着智能城市的不断发展&#xff0c;人们对于城市管理的要求也在不断提高&#xff0c;这就需要高效、智能的城市管理平台来实现。而三防平板就是一款可以满足这一需求的智能设备。 三防平板是一种集防水、防尘、防摔于一体的智能平板电脑&#xff0c;它可以在复杂的环境下稳定运…

python介绍,安装Cpython解释器,IDE工具pycharm的使用

python介绍 官方的Python解释器本质是基于C语言开发的一个软件&#xff0c;该软件的功能就是读取以py.结尾的文件内容&#xff0c;然后按照Guido定义好的语法和规则去翻译并执行相应的代码。这种C实现的解释器被称为Cpython。 python解释器的种类&#xff1a;Jython IPyth…

记录下ibus-libpinyin输入法的重新安装

目前的版本为&#xff1a; 首先把现在的ibus-libpinyin卸了 sudo apt-get --purge remove ibus-libpinyin sudo apt-get autoremove 安装教程请参考 Installation libpinyin/ibus-libpinyin Wiki GitHub yilai sudo apt install pkg-config sudo apt-get install lib…

实战分享:SpringBoot在创新创业项目管理中的应用

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Unity3d Shader篇(三)— 片元半兰伯特着色器解析

文章目录 前言一、片元半兰伯特着色器是什么&#xff1f;1. 片元漫反射着色器的工作原理2. 片元半兰伯特着色器的优缺点优点&#xff1a;缺点&#xff1a; 3. 公式 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函数5. 片元着色器函数…

QT设置qss

Qt设置qss文件&#xff08;设置在qrc中&#xff09; 1、右击项目选择添加新文件 2、在弹出的对话框中选择Qt -> Qt Resource File 3、随便起一个名称 4、在代码路径下新建一个stylesheet.qss文件&#xff0c;随便写入一些样式 5、右击resources.qrc&#xff0c;选择添加…

地理格网地址赋码过程

1.地址地名赋码流程 1.由镇街收集数据并且统一入库到地址数据库中; 2.进行地址字段的详细校验; 3.对进行校验通过的数据按照西湖区统一地址规则进行赋码 4.对进行校验失败的数据反馈成 execl 给镇街进行数据的核对校对 2地址校验规则 # 必填字段规范 省(字段名 - provinc…

进阶C语言-通讯录的实现

通讯录 🎈1.设计要求🎈2.程序实现🔭2.1打印菜单及初始化通讯录🔭2.2显示所有联系人🔭2.3查找指定的联系人🔭2.4删除指定的联系人🔭2.5查找指定的联系人🔭2.6修改指定联系人🔭2.7按照年龄排序(以此为例)🎈3.全部源码以及实现🎈1.设计要求 🌞通过前面…

SpringSecurity(17)——OAuth2令牌管理策略

刷新令牌策略 注意&#xff1a;刷新令牌只有在授权码模式和密码模式中才有&#xff0c;对应的指定这两种模式时&#xff0c;在类型上加上refresh_token <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-se…

【Flink入门修炼】1-1 为什么要学习 Flink?

流处理和批处理是什么&#xff1f; 什么是 Flink&#xff1f; 为什么要学习 Flink&#xff1f; Flink 有什么特点&#xff0c;能做什么&#xff1f; 本文将为你解答以上问题。 一、批处理和流处理 早些年&#xff0c;大数据处理还主要为批处理&#xff0c;一般按天或小时定时处…

如何在docker中访问电脑上的GPU?如何在docker中使用GPU进行模型训练或者加载调用?

如何在docker中访问电脑上的GPU&#xff1f;如何在docker中使用GPU进行模型训练或者加载调用&#xff1f; 其实使用非常简单&#xff0c;只是一行命令的事&#xff0c;最主要的事配置好驱动和权限。 docker run -it --rm --gpus all ycj520/centos:1.0.0 nvidia-smi先看看 st…

Kafka 使用手册

kafka3.0 文章目录 kafka3.01. 什么是kafka&#xff1f;2. kafka基础架构3. kafka集群搭建4. kafka命令行操作主题命令行【topic】生产者命令行【producer】消费者命令行【consumer】 5. kafka生产者生产者消息发送流程Producer 发送原理普通的异步发送带回调函数的异步发送同步…

Mac OS中创建适合网络备份的加密镜像文件:详细步骤与参数选择

这篇文章提供了在Mac OS中创建适合网络备份的加密镜像文件的详细步骤&#xff0c;同时探讨了在选择相关参数时的关键考虑因素&#xff0c;以确保用户能够安全、高效地存储和保护重要数据。 创建步骤 在Mac OS Monterey中&#xff0c;你可以使用“磁盘工具”&#xff08;Disk …

【C++】初始化列表--再谈构造函数

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

PXI-1 Peripheral Module 64Bit 改混合槽 PXI Express Hybrid Slot

PXI PXIEPXI_LBR05VauxPXI_LBR2WAKE#PXI_LBR3ALERT#PXI_LBR412VPXI_LBR512VPXI_LBRL0/PXI_STAR0GNDPXI_LBRL1/PXI_STAR1GNDPXI_LBRL2/PXI_STAR2GNDPXI_LBRL3/PXI_STAR33.3VPXI_LBRL4/PXI_STAR43.3VPXI_LBRL5/PXI_STAR53.3V 实际就是拆掉这个 红黄框里的端子。。