【代码随想录day58】【C++复健】 117. 软件构建(拓扑排序);47. 参加科学大会(dijkstra(朴素版)精讲)

117. 软件构建(拓扑排序)

继续边看解析边做题,思考时的问题做个如下的总结:

1. 存边用什么数据结构?

在题目中,我们需要存储节点之间的依赖关系(边信息)。选择适合的数据结构非常重要:

  • 选择 unordered_map<int, vector<int>>
    • 这个结构的作用是将节点 int 映射到一个 vector<int>,即以 O(1) 的复杂度找到所有依赖当前节点的节点集合。
    • 在代码中,rela[left].push_back(right) 表示从节点 left 指向节点 right 的边。

这种结构方便快捷,是处理稀疏图的常见选择。如果用二维数组存储,虽然逻辑上也可以,但会浪费内存并导致效率下降。

2 队列是否需要初始化代码?

自己思考的时候感觉队列需要一个初始化代码,但是却想不明白能不能合到主循环的代码里面去。看了卡哥的解析之后发现了,并不能,所以无须担心。

3 循环逻辑问题(GPT优化版)

我在写这道题时,曾经因为对循环逻辑的处理不当导致代码变成了死循环。具体问题是,我把初始化代码直接搬到了主循环里,导致一些节点被重复插入队列。比如,节点 1 在初始化时已经被插入队列了,但后面又因为错误的逻辑反复地被插入队列,这显然是不正确的。

当时我的想法是,在节点进入队列后,把它对应的 indegree 值设置成 -1,这样能避免重复插入。但是后来忘记实现这一点,结果还是出现了问题。虽然这种方式能够解决问题,但仔细想想,其实有更简单的方法:只要在 indegree[tominus[i]]--; 这一步之后,立即判断节点的入度是否减到 0,如果是 0,就将它加入队列。

这样处理有两个明显的优点:

  1. 避免重复插入节点: 减少入度操作的节点必然是与其他节点存在依赖关系的(即入度不为 0 的节点),只有在入度变为 0 时才会被加入队列,从逻辑上保证了节点最多只会入队一次。
  2. 减少不必要的遍历: 在减少入度时直接判断是否需要入队,避免了每次操作后全量扫描所有节点,显著提高了代码效率。

最终通过这样的调整,不仅解决了死循环问题,还让代码的逻辑更加清晰,执行效率也更高。这种在操作中即时判断的优化思路,给我很大的启发。

#include<iostream>
#include<vector>
#include<queue>
#include<unordered_map>
using namespace std;int main(){int n,m;cin >> n >> m;vector<int> indegree(n);vector<int> result;unordered_map<int, vector<int>> rela;for(int i=0; i<m; i++){int left, right;cin >> left >> right;indegree[right]++;rela[left].push_back(right);}queue<int> zerodegree;for(int i=0; i<n; i++){if(indegree[i] == 0){zerodegree.push(i);}}while(!zerodegree.empty()){int top = zerodegree.front();zerodegree.pop();result.push_back(top);vector<int> tominus = rela[top];for(int i=0; i<tominus.size(); i++){indegree[tominus[i]]--;if (indegree[tominus[i]] == 0) {zerodegree.push(tominus[i]);}}}if(result.size() == n){for(int i=0; i<n; i++){cout << result[i];if(i<n-1){cout << " ";}}return 0;}cout << -1;
}

47. 参加科学大会(dijkstra(朴素版)精讲)

虽然的确是第一次写最短路算法,也是边看着解析边做的,但确实感觉这个题和prim算法非常的像,只要稍微改一下更新的公式就行,自信就来了。

然后自己上手一写,一塌糊涂。

来看GPT给我分析的问题:

1. 未初始化输入的边信息

在读取边信息时,你直接将 distance[left][right] = val,但没有先读取 leftright,会导致程序读取未定义的值。

修正方法: 在读取边之前,添加 cin >> left >> right >> val

for (int i = 0; i < m; i++) {int left, right, val;cin >> left >> right >> val; // 读取边信息distance[left][right] = val;distance[right][left] = val;
}

并且这里其实还有一个更严肃的问题,那就是这是一个有向图而非无向图,所以我不能给左右赋同样的值(因为这个,做不对还想了半天),不然会导致算出来的结果不对,所以正确的应该是:

for (int i = 0; i < m; i++) {int left, right, val;cin >> left >> right >> val; // 读取边信息distance[left][right] = val;
}

2. 忘了在计算距离最小值的判断力加入对visited数组的判断

在第一个循环中,你将 visited[1] 设置为 true,但后续并没有在循环中检查哪些节点已经被访问过,可能会导致重复访问,或者访问逻辑错误。

修正方法: 在主循环和内层循环中,增加对 visited 的判断:

if (!visited[j] && mindist[j] < dis_min) {

3. 访问越界问题

当所有节点都访问过后,pos 可能仍然是 -1,表示当前没有未访问的节点。这会导致接下来的代码逻辑失效,导致访问出现越界问题。

修正方法: 在找到最小 pos 后立即判断:

if (pos == -1) {break; // 无法找到更短的路径,直接退出
}

 顺带一提,卡哥的做法是直接给pos赋值成1,这样即使是没找到,也不会导致访问越界。但这样做的坏处在于,卡哥的这种写法会让循环继续执行,但假设我们循环一整圈都没有找到比INT_MAX更小的距离,此时其实说明已经没边了,所以循环没有必要继续执行了,直接break掉还能省点事情。

脑子里的杠精:如果刚好有一个距离就等于INT_MAX,你这个判断不就失效了吗?

emm... 那如果是这样距离总和都超过INT能表示的范围了,不如放他一马。


4. 在更新距离时也忘了对visited数组的判断

if (!visited[k] && distance[pos][k] != INT_MAX) {mindist[k] = min(mindist[pos] + distance[pos][k], mindist[k]);
}

以上就是本期的全部内容了,喜欢不要忘了点个一键三连哦(串台)

#include<iostream>
#include<vector>
#include <climits>
using namespace std;int main(){int n,m;cin >> n >> m;vector<vector<int>> distance(n+1, vector<int>(n+1, INT_MAX));for(int i=0; i<m; i++){int left, right, val;cin >> left >> right >> val;distance[left][right] = val;//distance[right][left] = val; //不能加,加了你就完了}vector<int> mindist(n+1, INT_MAX);vector<bool> visited(n+1);mindist[1] = 0;for(int i=1; i<=n; i++){int dis_min = INT_MAX;int pos = -1;for(int j=1; j<=n; j++){if(!visited[j] && mindist[j] < dis_min){dis_min = mindist[j];pos = j;}}if (pos == -1) {break; // 无法找到更短的路径,直接退出}visited[pos] = true;for(int k=1; k<=n; k++){if(!visited[k] && distance[pos][k] != INT_MAX){mindist[k] = min(mindist[pos] + distance[pos][k], mindist[k]);}}}if(mindist[n] == INT_MAX){cout << -1;return 0;}cout << mindist[n];
}

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

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

相关文章

第九篇:k8s 通过helm发布应用

什么是helm&#xff1f; Helm 是 Kubernetes 的包管理器。Helm 是查找、分享和使用软件构建 Kubernetes 的最优方式。 在红帽系的Linux中我们使用yum来管理RPM包&#xff0c;类似的&#xff0c;在K8s中我们可以使用helm来管理资源对象&#xff08;Deployment、Service、Ingress…

OpenCV相机标定与3D重建(9)相机标定函数calibrateCameraRO()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::calibrateCameraRO 是 OpenCV 中用于相机标定的函数&#xff0c;它允许固定某些点来进行更精确的标定。 函数原型 double cv::calibrateCa…

【CSS in Depth 2 精译_072】第 12 章 CSS 排版与间距概述 + 12.1 间距设置(上):究竟该用 em 还是 px

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 12 章 CSS 排版与间距】 ✔️ 12.1 间距设置 ✔️ 12.1.1 使用 em 还是 px ✔️12.1.2 对行高的深入思考12.1.3 行内元素的间距设置 文章目录 第 12 章 排版与间距…

2024/12/12学习日志

为了更好地记录并反思自己的学习状况&#xff0c;将每日学习的内容、时长、心得等记录于此日志。 于9月3日开始记录&#xff0c;计划每日记录&#xff0c;希望至少能够坚持一个学期。 学习内容&#xff1a; 计组&#xff1a; 计算机架构 硬件的衡量指标&#xff1a;计算 编…

el-thee懒加载删除某条数据 ,el-thee懒加载重置,el-thee刷新某个节点

一、懒加载的tree已经全部展开&#xff0c;外部点击删除的时候不需要重新展开点击获取下一层数据 <template> <el-treeref"tree":data"treeData":props"defaultProps"render-after-expandhighlight-currentlazy:expand-on-click-node&q…

【问题记录】07 MAC电脑,使用FileZilla(SFTP)连接堡垒机不成功

项目场景&#xff1a; 使用MAC电脑&#xff0c;以子账号&#xff08;非root&#xff09;的形式登录&#xff0c;连接堡垒机CLB&#xff08;传统型负载均衡&#xff09;&#xff0c;使用FileZilla&#xff08;SFTP&#xff09;进行FTP文件传输。 问题描述&#xff1a; MAC电脑…

狗为啥会咬自己的尾巴

狗啃咬自己的尾巴&#xff0c;这一现象并非简单的好奇或贪玩之举&#xff0c;其背后可能隐藏着诸多复杂的原因&#xff0c;值得我们深入探究与深思。 从生理层面来看&#xff0c;尾巴部位出现皮肤疾病、寄生虫感染或受伤疼痛是常见诱因。例如&#xff0c;湿疹、跳蚤、蜱虫等问…

【数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 测试说明 我的通关代码: 测试结果&#xff1a; 任务描述 本关任务&#xff1a;编写一个程序实现顺序栈的基本运算。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 初始化栈、销毁栈、判断栈是否为空、进栈、出栈、取…

Codeforces Round 992 (Div. 2)

传送门&#xff1a;Dashboard - Codeforces Round 992 (Div. 2) - Codeforces A. Game of Division 思路&#xff1a;模拟 AC代码&#xff1a;Submission #295676347 - Codeforces B. Paint a Strip 思路&#xff1a;数学 贪心 放置的位置一定是 1 4 10 22 48 ....…

前端(五)css属性

css属性 文章目录 css属性一、字体属性二、文本属性三、背景属性四、盒子模型 一、字体属性 font-weight&#xff1a;文字粗细&#xff0c;在100到900之间&#xff0c;normal(400),bord(700),inherit(继承父类) font-style&#xff1a;文字风格&#xff0c;normal表示正常(默认…

Linux网络之“桥接模式”和“NAT模式”配置

介绍虚拟机的“桥接模式”和“NAT模式”配置。 1、“桥接模式”介绍 “桥接模式”将虚拟机的虚拟网络适配器与主机的“物理网络适配器”进行交接&#xff0c;虚拟机中的“虚拟网络适配器”通过主机中的“物理网络适配器”访问外部网络。物理主机的网卡好比是一个“虚拟的交换机…

shell编程(完结)

shell编程&#xff08;完结&#xff09; 声明&#xff01; 学习视频来自B站up主 ​泷羽sec​​ 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章 笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其…

爬虫自动化之drissionpage+SwitchyOmega实现随时切换代理ip

本文介绍了如何使用DrizzlePage进行爬虫自动化,并重点讲解了首次启动时设置代理IP以及通过SwitchyOmega插件实现随时切换代理IP的方法。 安装一次,后面调用就不会再去安装了 下载地址:https://github.com/FelisCatus/SwitchyOmega/releases 这两个文件随便那个都可以,下载…

Ariba Procurement: Administration_Integration Basics

Ariba Procurement: Administration_Integration Basics SAP Ariba 和SAP ERP 的主数据集成 对于主数据,CIG 仅仅做数据传输,在CIG系统里无任何转换逻辑。在CIG中,不需要给主数据创建项目。SAP中以所需的文件格式或模式提取主数据(MD)。文件格式为CSV。然后,所有文件都…

HDOJ 1735:字数统计 ← 贪心

【题目来源】https://acm.hdu.edu.cn/showproblem.php?pid1735【题目描述】 一天&#xff0c;淘气的 Tom 不小心将水泼到了他哥哥 Jerry 刚完成的作文上。原本崭新的作文纸顿时变得皱巴巴的&#xff0c;更糟糕的是由于水的关系&#xff0c;许多字都看不清了。可怜的 Tom 知道他…

Next.js配置教程:构建自定义服务器

更多有关Next.js教程&#xff0c;请查阅&#xff1a; 【目录】Next.js 独立开发系列教程-CSDN博客 目录 前言 1. 什么是自定义服务器&#xff1f; 2. 配置自定义服务器 2.1 基础配置 2.2 集成不同的服务器框架 使用Fastify 使用Koa 3. 自定义服务器的高级功能 3.1 路…

三对角矩阵@带状矩阵的压缩存储与还原

文章目录 三对角矩阵计算带状区域元素数量 压缩公式由 k k k确定 i , j i,j i,j确定 i ( k ) i(k) i(k)另一种表达式 确定 j ( k ) j(k) j(k)公式总结应用举例 三对角矩阵 对角矩阵也称带状矩阵。对 n n n 阶矩阵 A A A 中的任意一个元素 a i , j a_{i,j} ai,j​&#xff0…

解决创建laravel项目,使用国外镜像超时,国内镜像缺包的问题

解决创建laravel项目&#xff0c;使用国外镜像超时&#xff0c;国内镜像缺包的问题 一、前言二、切换镜像三、创建最新版本四、创建指定版本 一、前言 最近想下载 laravel 框架看看&#xff0c;但也遇到了些麻烦&#xff0c;这里做个记录。 二、切换镜像 先查看镜像源&#…

ThinkPHP 5.1 的模板布局功能

ThinkPHP 5.1 的模板布局功能&#xff0c;包括全局配置、模板标签以及动态方法布局三种方式。以下是对这三种方式的要点概括和补充&#xff0c;以便于更好地理解和使用&#xff1a; 方式一&#xff1a;全局配置方式 适用于全站使用相同布局的情况&#xff0c;配置简单且统一。…

静默活体识别API、静默活体识别sdk、C++集成

静默活体检测服务接口&#xff0c;是一种先进的生物特征认证技术&#xff0c;可对上传的人脸图像进行检测&#xff0c;确认图像中人脸是否为人体实时拍摄&#xff0c;基于深度学习算法&#xff0c;能够有效防止照片攻击、面具攻击、屏幕攻击等行为。 发展趋势 随着人工智能和机…