算法日记20:SC72最小生成树(prim朴素算法)

news2025/4/8 2:55:44

一、题目:

在这里插入图片描述

二、题解

在这里插入图片描述

2.1:朴素prim的步骤解析 O ( n 2 ) O(n^2) O(n2)(n<=1e3)

0、假设,我们现在有这样一个有权图

在这里插入图片描述

1、我们随便找一个点,作为起点开始构建最小生成树(一般是1号),并且存入intree[]状态数组中(该数组表示是否访问过了)

在这里插入图片描述

2、找所有点当中,距离intree[]最近的点,

  • 循环 n − 1 n-1 n1(因为已经确定了1这个点),每次找距离intree[]最近的点作为拓展点,
  • 即选择了[2]这个点
    在这里插入图片描述

3、把dis[2](2距离intree的距离)累计起来(res+=dis[2]),并且更新所有点的dis

在这里插入图片描述

4、此时,重复找所有点当中,距离intree[]最近的点(重复2/3)…

三、朴素prim代码解析

3.1、代码分块解析:

这段代码实现了 Prim 算法 用于求解 最小生成树,我会将代码分块并逐步解释每一块的作用。

1. 常量定义

const int N = 103;  // 设置最大点数
int a[N][N], dis[N];
bool st[N];
int n, m;

解释:

  • N 定义了图中点的最大数量,设置为 103。
  • a[N][N]:一个二维数组,表示图的邻接矩阵,存储两点之间的边权。
    • a[i][j]:表示i–>j的距离
  • dis[N]:一个一维数组,表示从起始点到每个节点的最短距离。
  • st[N]:布尔型数组,用来标记某个节点是否已经被加入最小生成树。(图解中的intree数组)
  • nm:分别表示图中的节点数和边数。

2. solve 函数的初始化

void solve()
{
   memset(dis, 0x3f, sizeof(dis));  // 初始化dis数组,设为最大值
   memset(a, 0x3f, sizeof(a));      // 初始化邻接矩阵为最大值

   // 初始化
   cin >> n >> m;
   for (int i = 1; i <= m; i++) 
   {
       int ui, vi, wi;
       cin >> ui >> vi >> wi;    
       a[ui][vi] = min(a[ui][vi], wi);
       a[vi][ui] = min(a[vi][ui], wi);
   }
   for (int i = 1; i <= n; i++) a[i][i] = 0;  // 自己到自己没有边,权重为 0

解释:

  • memset(dis, 0x3f, sizeof(dis)):将 dis 数组初始化为一个较大的值(通常为无穷大,表示尚未连接的节点)。
  • memset(a, 0x3f, sizeof(a)):将邻接矩阵 a 初始化为无穷大,表示两点之间如果没有边,则权重为无穷大。
  • 输入节点数 n 和边数 m,然后读入每条边的信息,更新邻接矩阵 a。同时,因为有可能存在重复边,所以采用 min 取最小边权,确保保存的是权重最小的边。
  • 设置每个节点到自身的距离为 0

3. 最小生成树的 Prim 算法核心部分

   dis[1] = 0;  // 从节点1开始,初始权重为0
   int res = 0;  // 记录最小生成树的总权重
   for (int i = 1; i <= n; i++) // 进行n次选择最小值操作
   {  
       int temp = -1;  // 用于记录当前最小值对应的节点
       
       // 遍历所有节点,找出距离最小的未加入最小生成树的节点
       for (int j = 1; j <= n; j++) 
       {  
       	//和Dijkstra一样,
       	//1.当j这个点还没访问过,2.遍历的的点j<当前点temp的距离,那么就更新temp
       	//temp==-1只是为了确保其能够第一次进入循环,详解看Dijkstra
           if (!st[j] && ((temp == -1) || (dis[j] < dis[temp]))) 
           {
               temp = j;
           }
       }
	   //此时temp就是距离intree最近的点
       if (temp == -1) // 如果所有节点都已经被选中,说明图不连通,直接return
       {  
           cout << -1 << '\n';
           return; 
       }

解释:

  • 初始化 dis[1] = 0,表示从节点 1 开始构建最小生成树,起始点的距离为 0
  • res 用来记录最小生成树的总权重。
  • 外层 for (int i = 1; i <= n; i++) 进行 n 次选择最小值操作,每次选择一个最小的未加入最小生成树的节点。
  • 内层循环 for (int j = 1; j <= n; j++) 遍历所有节点,找出距离当前生成树最近的节点。条件是节点未加入生成树 !st[j]dis[j] 小于当前最小值。
  • temp == -1 用来判断是否图不连通。如果没有找到最小值节点,说明图是断开的,输出 -1

4. 更新最小生成树的权重并松弛边

       res += dis[temp];  // 将当前最小值加到结果中
       st[temp] = true;    // 标记节点temp已加入最小生成树
       dis[temp] = 0;      // 当前节点到自己的距离设为0(实际上不影响结果)

       for (int i = 1; i <= n; i++) {  // 松弛与temp相连的所有边
           if (!st[i]) {  // 只有未加入最小生成树的节点才能被松弛
               dis[i] = min(dis[i], a[temp][i]);
           } 
       }    
   }
   cout << res << '\n';  // 输出最小生成树的总权重
}

解释:

  • 将选中的最小值节点 temp 的距离 dis[temp] 加到总权重 res 中。
  • 标记该节点已经被加入最小生成树,即 st[temp] = true
  • 进行 松弛操作,尝试更新与当前最小值节点相连的所有边的权重,更新未加入生成树的节点的最短距离 dis[i]

3.2、完整代码

#include<bits/stdc++.h>
using namespace std;

const int N=103;
struct node{
   int v;//指向点
   int w;//权重
};
int a[N][N],dis[N];
bool st[N];
int n,m;


void solve()
{
   memset(dis,0x3f,sizeof(dis));
   memset(a,0x3f,sizeof(a));

   //初始化
   cin>>n>>m;
   for(int i=1;i<=m;i++)
   {
       int ui,vi,wi;cin>>ui>>vi>>wi;    
       //g[ui].push_back({vi,wi});
       a[ui][vi]=min(a[ui][vi],wi);
       a[vi][ui]=min(a[vi][ui],wi);
   }
   for(int i=1;i<=n;i++) a[i][i]=0;
   
   dis[1]=0; //从1开始,1的权重为0
   int res=0;
   for(int i=1;i<=n;i++)   //找n次最小值
   {
       int temp=-1;    //表示dis最小点
       for(int j=1;j<=n;j++)   //遍历每个点找最小值
       {
           //如果j还没被选中过
           if(!st[j] && ((temp==-1)||(dis[j]<dis[temp])))
           {
               temp=j;
           }
       }

        if (temp == -1) // 如果没有点可选,说明图不连通
        {
           cout<<-1<<'\n';
           break; 
        }
       //此时表示已经选中了最小值temp
       res+=dis[temp];
       st[temp]=true;
       dis[temp]=0;//距离设置为0

       for(int i=1;i<=n;i++)    //松弛temp相连的边a[temp][i]
       {
           if(!st[i]) //表示i话没有松弛过
           {
               dis[i]=min(dis[i],a[temp][i]);
           } 
       }    
   }
   cout<<res<<'\n';
} 

   

int main()
{
   ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
   int _=1;
   while(_--) solve();
   return 0;
}

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

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

相关文章

Redis7——基础篇(五)

前言&#xff1a;此篇文章系本人学习过程中记录下来的笔记&#xff0c;里面难免会有不少欠缺的地方&#xff0c;诚心期待大家多多给予指教。 基础篇&#xff1a; Redis&#xff08;一&#xff09;Redis&#xff08;二&#xff09;Redis&#xff08;三&#xff09;Redis&#x…

从零搭建微服务项目Base(第7章——微服务网关模块基础实现)

前言&#xff1a; 在前面6章的学习中已经完成了服务间的调用实现&#xff0c;即各微服务通过nacos或eureka服务器完成服务的注册&#xff0c;并从nacos中拉取配置实现热更新。当某个服务接口需要调用其他服务时&#xff0c;通过feign定义接口&#xff0c;并通过注解配置服务名…

pdf转换成word在线 简单好用 支持批量转换 效率高 100%还原

pdf转换成word在线 简单好用 支持批量转换 效率高 100%还原 在数字化办公的浪潮中&#xff0c;文档格式转换常常让人头疼不已&#xff0c;尤其是 PDF 转 Word 的需求极为常见。PDF 格式虽然方便阅读和传输&#xff0c;但难以编辑&#xff0c;而 Word 格式却能灵活地进行内容修…

嵌入式音视频开发(二)ffmpeg音视频同步

系列文章目录 嵌入式音视频开发&#xff08;零&#xff09;移植ffmpeg及推流测试 嵌入式音视频开发&#xff08;一&#xff09;ffmpeg框架及内核解析 嵌入式音视频开发&#xff08;二&#xff09;ffmpeg音视频同步 嵌入式音视频开发&#xff08;三&#xff09;直播协议及编码器…

SpringBoot速成概括

视频&#xff1a;黑马程序员SpringBoot3Vue3全套视频教程&#xff0c;springbootvue企业级全栈开发从基础、实战到面试一套通关_哔哩哔哩_bilibili 图示&#xff1a;

微信小程序image组件mode属性详解

今天学习微信小程序开发的image组件&#xff0c;mode属性的属性值不少&#xff0c;一开始有点整不明白。后来从网上下载了一张图片&#xff0c;把每个属性都试验了一番&#xff0c;总算明白了。现总结归纳如下&#xff1a; 1.使用scaleToFill。这是mode的默认值&#xff0c;sc…

Matlab写入点云数据到Rosbag

最近有需要读取一个点云并做处理后&#xff0c;重新写回rosbag。网上有很多读取的教程&#xff0c;但没有写入。自己写入时也遇到了很多麻烦&#xff0c;踩了一堆坑进行记录。 1. rosbag中一个lidar的msg有哪些信息&#xff1f; 通过如下代码&#xff0c;先读取一个rosbag的l…

数据分析--数据清洗

一、数据清洗的重要性&#xff1a;数据质量决定分析成败 1.1 真实案例警示 电商平台事故&#xff1a;2019年某电商大促期间&#xff0c;因价格数据未清洗导致错误标价&#xff0c;产生3000万元损失医疗数据分析&#xff1a;未清洗的异常血压值&#xff08;如300mmHg&#xff…

用命令模式设计一个JSBridge用于JavaScript与Android交互通信

用命令模式设计一个JSBridge用于JavaScript与Android交互通信 在开发APP的过程中&#xff0c;通常会遇到Android需要与H5页面互相传递数据的情况&#xff0c;而Android与H5交互的容器就是WebView。 因此要想设计一个高可用的 J S B r i d g e JSBridge JSBridge&#xff0c;不…

Vue 3最新组件解析与实践指南:提升开发效率的利器

目录 引言 一、Vue 3核心组件特性解析 1. Composition API与组件逻辑复用 2. 内置组件与生命周期优化 3. 新一代UI组件库推荐 二、高级组件开发技巧 1. 插件化架构设计 2. 跨层级组件通信 三、性能优化实战 1. 惰性计算与缓存策略 2. 虚拟滚动与列表优化 3. Tree S…

计算机网络(涵盖OSI,TCP/IP,交换机,路由器,局域网)

一、网络通信基础 &#xff08;一&#xff09;网络通信的概念 网络通信是指终端设备之间通过计算机网络进行的信息传递与交流。它类似于现实生活中的物品传递过程&#xff1a;数据&#xff08;物品&#xff09;被封装成报文&#xff08;包裹&#xff09;&#xff0c;通过网络…

JVM-Java程序的运行环境

Java Virtual Machine Java程序的运行环境 JVM组成 程序计数器 线程私有的&#xff0c;内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。 Java堆 线程共享的区域: 主要用来保存对象实例, 数组等, 当堆中没有内存空间可分配给实例也无法再扩展时, 则抛出OutOfMe…

什么是网关,网关的作用是什么?网络安全零基础入门到精通实战教程!

1. 什么是网关 网关又称网间连接器、协议转换器&#xff0c;也就是网段(局域网、广域网)关卡&#xff0c;不同网段中的主机不能直接通信&#xff0c;需要通过关卡才能进行互访&#xff0c;比如IP地址为192.168.31.9(子网掩码&#xff1a;255.255.255.0)和192.168.7.13(子网掩码…

《千恋万花》无广版手游安卓苹果免费下载直装版

自取https://pan.xunlei.com/s/VOJS77k8NDrVawqcOerQln2lA1?pwdn6k8 《千恋万花》&#xff1a;柚子社的和风恋爱杰作 《千恋万花》&#xff08;Senren * Banka&#xff09;是由日本知名美少女游戏品牌柚子社&#xff08;Yuzusoft&#xff09;于2016年推出的一款和风恋爱题材…

javaEE-14.spring MVC练习

目录 1.加法计算器 需求分析: 前端页面代码: 后端代码实现功能: 调整前端页面代码: 进行测试: 2.用户登录 需求分析: 定义接口: 1.登录数据校验接口: 2.查询登录用户接口: 前端代码: 后端代码: 调整前端代码: 测试/查错因 后端: 前端: lombok工具 1.引入依赖…

rabbitmq五种模式的实现——springboot

rabbitmq五种模式的实现——springboot 基础知识和javase的实现形式可以看我之前的博客 代码地址&#xff1a;https://github.com/9lucifer/rabbitmq4j-learning 一、进行集成 &#xff08;一&#xff09;Spring Boot 集成 RabbitMQ 概述 Spring Boot 提供了对 RabbitMQ 的自…

23. AI-大语言模型-DeepSeek赋能开发-Spring AI集成

文章目录 前言一、Spring AI 集成 DeepSeek1. 开发AI程序2. DeepSeek 大模型3. 集成 DeepSeek 大模型1. 接入前准备2. 引入依赖3. 工程配置4. 调用示例5. 小结 4. 集成第三方平台&#xff08;已集成 DeepSeek 大模型&#xff09;1. 接入前准备2. POM依赖3. 工程配置4. 调用示例…

Educational Codeforces Round 174 (Rated for Div. 2)(ABCD)

A. Was there an Array? 翻译&#xff1a; 对于整数数组 ​&#xff0c;我们将其相等特征定义为数组 &#xff0c;其中&#xff0c;如果数组 a 的第 i 个元素等于其两个相邻元素&#xff0c;则 &#xff1b;如果数组 a 的第 i 个元素不等于其至少一个相邻元素&#xff0c;则 …

如何在本机上模拟IP地址

如何在本机上模拟IP地址 前言 在某些开发或测试场景中&#xff0c;我们可能需要在本机上模拟一个指定的 IP 地址&#xff0c;并让局域网内的其他设备能够通过该 IP 访问本机提供的服务&#xff08;如 Web 服务&#xff09;。 本文将详细介绍如何在 Windows 和 macOS 系统上实…

【嵌入式Linux应用开发基础】进程间通信(1):管道

目录 一、管道的基本概念 二、管道的工作原理 三、管道的类型 3.1. 匿名管道&#xff08;Anonymous Pipe&#xff09; 3.2. 命名管道&#xff08;Named Pipe&#xff0c;FIFO&#xff09; 四、管道的读写规则 4.1. 匿名管道的读写规则 4.2. 命名管道的读写规则 五、管…