当前位置: 首页 > news >正文

详解 Prim 算法的实现

一、算法思路

Prim 算法是用来求最小生成树的,它的思想也有点类似于贪心——逐个将离当前集合最近的点加入到集合中,直至发现图不连通或所有点都被加到集合中,算法即宣告终止。它的具体做法是:

  • step 1:初始时,由当前最小生成树中的点构成的集合 S S S 为空,图中剩余的点到集合的距离皆为 + ∞ +\infty +,这一步可以用代码实现如下:

    // 假定图中共有N个点
    bool st[N]; // 用bool数组st来模拟集合S,若一个点i被加入集合,// 则将st[i]置为true
    int dist[N]; // 用dist数组来记录所有点到当前集合的最短距离,
    memset(dist, 0x3f, sizeof dist); // 初始时,将所有点到集合的最短// 距离置为正无穷
    
  • step 2:接下来是 n 轮循环,每轮循环的任务是找到当前离集合最近的点并将其加入集合(即合并到当前的最小生成树上),同时,用这个点更新其他点到集合的距离(当这个点加入集合后,其他点到集合的最短距离有可能发生改变,因为此时这个新加入的点也是集合的一部分了,所以要用这个点到其他点的距离来更新其他点到集合的最短距离),这一步的代码可以实现如下:

    // n是图中所有点的个数
    for (int i = 0; i < n; i++) // n轮循环,每轮循环负责将一个点加入集合中
    {// 首先要找到我们要加入的点是谁int t = -1; // 先用-1来暂时表示这个点,并用t来记录// 执行具体的寻找过程:从1~n这n个点中将当前这一轮的t找出来for (int j = 1; j <= n; j++) // 从1到n循环n个点,看哪个点符合要求if (!st[t] && (t == -1 || dist[j] < dist[t])) // 如果这个点尚未在集合中,并且// 要么找到了第一个不在集合中的点,// 要么找到了离集合最短距离更小的点t = j; // 就更新t的取值// 当我们找到t以后,我们需要将t加入到集合中,st[t] = true;// 并用t到其他点的距离更新其他点到集合的最短距离for (int j = 1; j <= n; j++)dist[j] = min(dist[j], g[t][j]);
    }
    
  • step 3:如何返回最终的结果呢?我们要找的是我们要返回的是最小生成树的树边权重之和(以下简记为“最小生成树的长度”),而这个长度是由一条条边加起来得到的。注意到,每次往集合中新加入一个点,就相当于当前最小生成树又多了一条边,而这条边就是我们要找的众多边之一。因此,只需要在每次新加入一条边的时候,把新加入的边的长度累加到最终的结果中去即可(这个长度即为新加入的点到集合的最短距离,即为 dist[t])。
    然而如果图中根本就不存在最小生成树怎么办呢?如果在中途就发现了图中必然不可能存在最小生成树,那能不能提前停止并返回结果呢?如果可以,当如何实现呢?
    答案是我们可以在加入每个点之前先做一个判断:如果新加入的点到集合的最短距离是 + ∞ +\infty + ,这就意味着新加入的点跟集合中的点根本就不连通,此时图中必不可能存在最小生成树,而一旦我们发现了这样一种情况,就可以提前退出循环,并将当前结果报告出去,其实现代码如下:

    // 用res来记录最终最小生成树的长度
    int res = 0; // 初始时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[j] < dist[t]))t = j;// 找到t以后,这个t不一定是与当前集合连通的,所以可以提前做一个判断:if (i && dist[t] == INF) return INF; // 如果当前点到集合的最短距离为正无穷,则返回正无穷(最终可根据返回结果是否为正无穷来判断图中是否存在最小生成树)// 如果上一步没有提前返回,则说明当前点与集合是连通的,那么它与集合之间将会连起一条新的边,这个边是最终最小生成树的一部分,要将它累加至最后的结果中:if (i) res += dist[t];// 注意以上两步中都有一个if(i),这个判断的目的是:i=0表示第一轮循环(即将第一个点加入最小生成树),由于第一个点到初始空集合S的距离为正无穷,所以这个点不能作为“不存在最小生成树”的判断,这个点到集合的距离也不能累加至最终的结果中,因此正确的做法是跳过这个点,即加一个if(i)的判断...// 最终返回res即可return res;
    }
    

二、Prim 算法求最小生成树的完整代码如下:

#include <iostream>
#include <cstring>using namespace std;const int N = 510, M = 2e5 + 10; // 边数设为初始值的两倍,是因为无向图要加两条有向边
const int 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; // 用res记录最终最小生成树的长度for (int i = 0; i < n; i++) // 然后开始n轮循环,每轮将一个点加入当前集合中{int t = -1; // 将当轮要加入的点初始化为-1for (int j = 1; j <= n; j++) // 然后从1~n这n个点中找到当前这一轮要加入的点if (!st[j] && (t == -1 || dist[j] < dist[t]))t = j;// 找到以后,先做判断,看图会不会不连通if (i && dist[t] == INF) return INF;// 如果确认当前这一轮还未发现图是不是不连通的,就先将当前边累加至最终结果if (i) res += dist[t];// 关键一步:用t到它所有邻居的距离更新它的所有邻居到当前集合的最短距离for (int j = 1; j <= n; j++) // 遍历并找到t的所有邻居dist[j] = min(dist[j], g[t][j]); // 更新邻居到当前集合的距离// 最后,将当前这个点t加入到当前集合中st[t] = true;}return res; // 返回图中最小生成树的长度
}int main()
{cin >> n >> m;memset(g, 0x3f, sizeof g); // 初始时,设置所有边权都为正无穷// 这一步是不可省略的,因为有些点之间根本就没有连接,其距离为正无穷,// 如果不进行这一步设置,这些不连通的点之间的边将被默认初始化为0,// 这显然是不对的while (m--){int a, b, w;scanf("%d%d%d", &a, &b, &w);g[a][b] = g[b][a] = min(g[a][b], w);}int res = prim();if (res == INF) puts("impossible");else cout << res << endl;return 0;
}

【注】以上内容参考AcWing。

相关文章:

详解 Prim 算法的实现

一、算法思路 Prim 算法是用来求最小生成树的&#xff0c;它的思想也有点类似于贪心——逐个将离当前集合最近的点加入到集合中&#xff0c;直至发现图不连通或所有点都被加到集合中&#xff0c;算法即宣告终止。它的具体做法是&#xff1a; step 1&#xff1a;初始时&#xf…...

Android 使用高德地图

一、获取高德平台key 【1】基于application包名&sha1值在高德控制台获取key值&#xff0c;详情参考&#xff1a; 获取Key-创建工程-开发指南-Android 地图SDK | 高德地图API 【2】在manifest中声明权限 【3】将拿到的key值在manifest中进行声明 <!--允许程序打开网络…...

从redis setnx 来看看分布式锁

什么是分布式锁 分布式锁&#xff08;多服务共享锁&#xff09;在分布式的部署环境下&#xff0c;通过锁机制来让多客户端互斥的对共享资源进行访问/操作。 为什么需要分布式锁 在单体应用服务里&#xff0c;不同的客户端操作同一个资源&#xff0c;我们可以通过操作系统提供…...

校园网网络规划与设计——计算机网络实践报告

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 目录 一、设计目的 二、软硬件环境 三、理论基础 四、设计方案 五、网络配置步骤 六、设计过程中出现的问题及相应解决办法 八、参考资料 一、设计目的 深入理解网络工程的三层层次设计模型&#xff1b; 掌握网络…...

Qt QScrollArea 不显示滚动条 不滚动

使用QScrollArea时&#xff0c;发现添加的控件超出QScrollArea 并没有显示&#xff0c;且没有滚动条效果 原因是 scrollArea指的是scrollArea控件本身的大小&#xff0c;肉眼能看到的外形尺寸。 scrollAreaWidgetContents指的是scrollArea控件内部的显示区域&#xff0c;里面可…...

【SVN在Linux下的常用指令】

windows下的TortoiseSVN是资源管理器的一个插件&#xff0c;以覆盖图标表示文件状态&#xff0c;几乎所以命令都有图形界面支持&#xff0c;比较好用&#xff0c;这里就不多说。主要说说linux下svn的使用&#xff0c;因为linux下大部分的操作都是通过命令行来进行&#xff0c;所…...

2024 高级前端面试题之 Node 「精选篇」

该内容主要整理关于 Node 模块的相关面试题&#xff0c;其他内容面试题请移步至 「最新最全的前端面试题集锦」 查看。 Node模块精选篇 1. package.json版本号规则2. package.json 与 package-lock.json 的关3. npm 模块安装机制4. 模块化的差异 AMD CMD COMMONJS ESMODUL5. No…...

linux麒麟系统安装mongodb7.0

1.mogedb下载 下载的是他tar包 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz wget -o https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz 也可以下载rpm包 2.将包上传至服务器并解压 #进入目录 并解压 cd /opt/ tar…...

Spring声明式事务

1.概念 事务就是用户定义的一系列执行SQL语句的操作, 这些操作要么完全地执行&#xff0c;要么完全地都不执行&#xff0c; 它是一个不可分割的工作执行单元 一个使用Mybatis-Spring的主要原因是它允许Mybatis参与到Spring的事务管理中&#xff0c;而不是给Mybatis创建一个新的…...

PyTorch深度学习实战(34)——Pix2Pix详解与实现

PyTorch深度学习实战&#xff08;34&#xff09;——Pix2Pix详解与实现 0. 前言1. 模型与数据集1.1 Pix2Pix 基本原理1.2 数据集分析1.3 模型构建策略 2. 实现 Pix2Pix 生成图像小结系列链接 0. 前言 Pix2Pix 是基于生成对抗网络 (Convolutional Generative Adversarial Netwo…...

第96讲:MySQL高可用集群MHA的核心概念以及集群搭建

文章目录 1.MHA高可用数据库集群的核心概念1.1.主从复制架构的演变1.2.MHA简介以及架构1.3.MHA的软件结构1.4.MHA Manager组件的启动过程1.5.MHA高可用集群的原理 2.搭建MHA高可用数据库集群2.1.环境架构简介2.2.搭建基于GTID的主从复制集群2.2.1.在三台服务器中分别搭建MySQL实…...

外星人入侵(python)

前言 代码来源《python编程从入门到实践》Eric Matthes 署 袁国忠 译 使用软件&#xff1a;PyCharm Community Editor 2022 目的&#xff1a;记录一下按照书上敲的代码 alien_invasion.py 游戏的一些初始化设置&#xff0c;调用已经封装好的函数方法&#xff0c;一个函数的…...

Unity中开发程序打包发布

添加ESC脚本 使用Unity打包发布的过程中&#xff0c;考虑到打开的程序会处于全屏界面&#xff0c;而此时我们又会有退出全屏的需求&#xff0c;因此需要添加ESC脚本&#xff0c;当我们单击ESC脚本的过程中&#xff0c;退出全屏模式。 在Assets/Scenes下&#xff0c;创建esc.cs…...

2024.2.1日总结

web的运行原理&#xff1a; 用户通过浏览器发送HTTP请求到服务器&#xff08;网页操作&#xff09;。web服务器接收到用户特定的HTTP请求&#xff0c;由web服务器请求信息移交给在web服务器中部署的javaweb应用程序&#xff08;Java程序&#xff09;。启动javaweb应用程序执行…...

​LeetCode解法汇总2670. 找出不同元素数目差数组

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 给你一个下…...

STM32目录结构

之前一直头疼的32目录&#xff0c;比51复杂&#xff0c;又没有C规律&#xff0c;也不像python脚本文件关联不强&#xff0c;也不像工整的FPGA工程&#xff0c;编的时候到处放&#xff0c;爆出的错千奇百怪。短暂整理了一个&#xff0c;还是没有理得很轻。 startup_stm32f10x_m…...

算法专题:记忆搜索

参考练习习题总集 文章目录 前置知识练习习题87. 扰乱字符串97. 交错字符串375. 猜数字大小II403. 青蛙过河464. 我能赢吗494. 目标和552. 学生出勤记录II576. 出借的路径数 前置知识 没有什么特别知识&#xff0c;只有一些做题经验。要做这类型的题目&#xff0c;首先写出暴…...

【数据分享】1929-2023年全球站点的逐日最低气温数据(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;其中又以气温指标最为常用&#xff01;说到气温数据&#xff0c;最详细的气温数据是具体到气象监测站点的气温数据&#xff01; 之前我们分享过1929-2023年全球气象站…...

2024美赛数学建模D题思路+模型+代码+论文(持续更新)

2024美赛数学建模A题B题C题D题E题F题思路模型代码论文&#xff1a;开赛后第一时间更新&#xff0c;获取见文末名片 组队环节&#xff1a; 美赛最多是3个人参赛&#xff0c;一般的队伍都是由三人组成&#xff08;当然如果你很大佬也可以一个人参赛&#xff09;&#xff0c;队伍…...

dubbo+sentinel最简集成实例

说明 在集成seata后&#xff0c;下面来集成sentinel进行服务链路追踪管理&#xff5e; 背景 sample-front网关服务已配置好 集成 一、启动sentinel.jar 1、官网下载 选择1:在本地启动 nohup java -Dserver.port8082 -Dcsp.sentinel.dashboard.serverlocalhost:8082 -Dp…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...