代码随想录Day51图:dijkstra(堆优化版)_Bellman_ford 算法 📅 发布时间:2026/7/5 10:14:24 👁️ 浏览次数: 代码随想录Day51图dijkstra堆优化版_Bellman_ford 算法dijkstra堆优化版题目小明是一位科学家他需要参加一场重要的国际科学大会以展示自己的最新研究成果。小明的起点是第一个车站终点是最后一个车站。然而途中的各个车站之间的道路状况、交通拥堵程度以及可能的自然因素如天气变化等不同这些因素都会影响每条路径的通行时间。小明希望能选择一条花费时间最少的路线以确保他能够尽快到达目的地。输入描述第一行包含两个正整数第一个正整数 N 表示一共有 N 个公共汽车站第二个正整数 M 表示有 M 条公路。接下来为 M 行每行包括三个整数S、E 和 V代表了从 S 车站可以单向直达 E 车站并且需要花费 V 单位的时间。输出描述输出一个整数代表小明从起点到终点所花费的最小时间。链接https://kamacoder.com/problempage.php?pid1047朴素版的dijkstra是从节点角度去做的如果是稀疏图很多节点很少的边那么空间就会造成浪费。图的存储方式邻接矩阵使用二维数组来表示图结构。 邻接矩阵是从节点的角度来表示图有多少节点就申请多大的二维数组。这种表达方式邻接矩阵在边少节点多的情况下会导致申请过大的二维数组造成空间浪费。而且在寻找节点链接情况的时候需要遍历整个矩阵即 n * n 的时间复杂度同样造成时间浪费。邻接表使用 数组 链表的方式来表示。 邻接表是从边的数量来表示图有多少边 才会申请对应大小的链表。本题从边的角度出发在处理三部曲里的第一步选源点到哪个节点近且该节点未被访问过的时候可以不用去遍历所有节点了。直接把边带权值加入到小顶堆利用堆来自动排序那么每次我们从堆顶里取出边自然就是距离源点最近的节点所在的边。用邻接表来存储邻接表用数组链表来表示ListList grid new ArrayList(n 1);但是本题中边是有权值的权值怎么表示那么里面的链表就不能使用int了而是需要一个键值对来存两个数字一个数表示节点一个数表示指向该节点的这条边的权值ListListpairint,int grid但是在代码中使用 pairint, int 很容易让我们搞混了第一个int 表示什么第二个int表示什么导致代码可读性很差。那么可以定义一个类来取代 pairint, intclassEdge{intto;// 邻接顶点intval;// 边的权重Edge(intto,intval){this.toto;this.valval;}}堆优化细节思路依然是 dijkstra 三部曲第一步选源点到哪个节点近且该节点未被访问过。第二步该最近节点被标记访问过。第三步更新非访问节点到源点的距离即更新minDist数组。第一步之前是通过遍历节点来遍历边通过两层for循环来寻找距离源点最近节点。这次我们直接遍历边且通过堆来对边进行排序达到直接选择距离源点最近节点。我们要选择距离源点近的节点即该边的权值最小所以我们需要一个小顶堆来帮我们对边的权值排序每次从小顶堆堆顶取边就是权值最小的边。有了小顶堆自动对边的权值排序那我们只需要直接从堆里取堆顶元素小顶堆中最小的权值在上面就可以取到离源点最近的节点了 未访问过的节点不会加到堆里进行排序第二步该最近节点被标记访问过这个就是将节点做访问标记和朴素dijkstra一样。第三步更新非访问节点到源点的距离这里的思路也是和朴素dijkstra一样的。朴素版本是这样做的//更新非访问节点到源点的距离即更新minDist数组for(intv1;vn;v){if(!visited[v]grid[cur][v]!INT_MAXminDist[cur]grid[cur][v]minDist[v]){minDist[v]minDist[cur]grid[cur][v];}}其中for循环是为了找到节点cur 链接指向了哪些节点因为使用邻接矩阵的表达方式 所以把所有节点遍历一遍。在邻接表中我们要获取节点cur 链接指向哪些节点就是遍历 grid[cur节点编号] 这个链表。堆优化版本和朴素版本的区别邻接表的表示方式不同。使用优先级队列小顶堆来对新链接的边排序。importjava.util.*;classEdge{intto;//邻接顶点intval;//边的权重Edge(intto,intval){this.toto;this.valval;}}classPairU,V{publicfinalUfirst;publicfinalVsecond;publicPair(Ufirst,Vsecond){this.firstfirst;this.secondsecond;}}classMycomparsionimplementsComparatorPairInteger,Integer{publicintcompare(PairInteger,Integerlhs,PairInteger,Integerrhs){returnInteger.compare(lhs.second,rhs.second);}}publicclassMain{publicstaticvoidmain(String[]args){ScannerscnewScanner(System.in);intnsc.nextInt();intmsc.nextInt();ListListEdgegridnewArrayList(n1);for(inti0;in;i){grid.add(newArrayList());}for(inti0;im;i){intp1sc.nextInt();intp2sc.nextInt();intvalsc.nextInt();grid.get(p1).add(newEdge(p2,val));}intstart1;intendn;int[]mindistnewint[n1];Arrays.fill(mindist,Integer.MAX_VALUE);boolean[]visitednewboolean[n1];// 优先队列中存放 Pair节点源点到该节点的权值PriorityQueuePairInteger,IntegerpqnewPriorityQueue(newMycomparsion());pq.add(newPair(start,0));// 初始化队列源点到源点的距离为0所以初始为0mindist[start]0;//起始点到自身的距离为0while(!pq.isEmpty()){PairInteger,Integercurpq.poll();if(visited[cur.first])continue;visited[cur.first]true;for(Edgeedge:grid.get(cur.first)){// 遍历 cur指向的节点cur指向的节点为 edge// cur指向的节点edge.to这条边的权值为 edge.valif(!visited[edge.to]mindist[cur.first]edge.valmindist[edge.to]){// 更新minDistmindist[edge.to]mindist[cur.first]edge.val;pq.add(newPair(edge.to,mindist[edge.to]));}}}if(mindist[end]Integer.MAX_VALUE){System.out.println(-1);// 不能到达终点}else{System.out.println(mindist[end]);// 到达终点最短路径}}}Bellman_ford 算法题目某国为促进城市间经济交流决定对货物运输提供补贴。共有 n 个编号为 1 到 n 的城市通过道路网络连接网络中的道路仅允许从某个城市单向通行到另一个城市不能反向通行。网络中的道路都有各自的运输成本和政府补贴道路的权值计算方式为运输成本 - 政府补贴。权值为正表示扣除了政府补贴后运输货物仍需支付的费用权值为负则表示政府的补贴超过了支出的运输成本实际表现为运输过程中还能赚取一定的收益。请找出从城市 1 到城市 n 的所有可能路径中综合政府补贴后的最低运输成本。如果最低运输成本是一个负数它表示在遵循最优路径的情况下运输过程中反而能够实现盈利。城市 1 到城市 n 之间可能会出现没有路径的情况同时保证道路网络中不存在任何负权回路。负权回路是指一系列道路的总权值为负这样的回路使得通过反复经过回路中的道路理论上可以无限地减少总成本或无限地增加总收益。输入描述第一行包含两个正整数第一个正整数 n 表示该国一共有 n 个城市第二个整数 m 表示这些城市中共有 m 条道路。接下来为 m 行每行包括三个整数s、t 和 v表示 s 号城市运输货物到达 t 号城市道路权值为 v单向图。输出描述如果能够从城市 1 到连通到城市 n 请输出一个整数表示运输成本。如果该整数是负数则表示实现了盈利。如果从城市 1 没有路径可达城市 n请输出 “unconnected”。链接https://kamacoder.com/problempage.php?pid1152本题依然是单源最短路问题求从节点1 到节点n的最小费用。 但本题不同之处在于边的权值是有负数了。Bellman_ford算法的核心思想是对所有边进行松弛n-1次操作n为节点数量从而求得目标最短路。什么是对边进行松弛举例minDist[B] 表示到达B节点最小权值minDist[B] 有哪些状态可以推出来状态一 minDist[A] value 可以推出 minDist[B] 。状态二 minDist[B]本身就有权值 可能是其他边链接的节点B 例如节点C以至于 minDist[B]记录了其他边到minDist[B]的权值minDist[B] 如何取舍。本题我们要求最小权值那么这两个状态我们就取最小的if (minDist[B] minDist[A] value) minDist[B] minDist[A] value。也就是说如果通过 A 到 B 这条边可以获得更短的到达B节点的路径即如果 minDist[B] minDist[A] value那么我们就更新 minDist[B] minDist[A] value 这个过程就叫做 “松弛” 。模拟过程使用minDist数组来表达起点到各个节点的最短距离。起点为节点1 起点到起点的距离为0所以 minDist[1] 初始化为0。对所有边进行第一次松弛示例给出的所有边为5 6 -21 2 15 3 12 5 22 4 -34 6 41 3 5节点5 - 节点6权值为-2 minDist[5] 还是默认数值max所以不能基于节点5去更新节点6。节点1 - 节点2权值为1 minDist[2] minDist[1] 1 更新 minDist[2] minDist[1] 1 0 1 1。节点5 - 节点3权值为1 minDist[5] 还是默认数值max所以不能基于节点5去更新节点3。节点2 - 节点5权值为2 minDist[5] minDist[2] 2 经过上面的计算minDist[2]已经不是默认值而是 1更新 minDist[5] minDist[2] 2 1 2 3。节点2 - 节点4权值为-3 minDist[4] minDist[2] (-3)更新 minDist[4] minDist[2] (-3) 1 (-3) -2节点4 - 节点6权值为4 minDist[6] minDist[4] 4更新 minDist[6] minDist[4] 4 -2 4 2节点1 - 节点3权值为5 minDist[3] minDist[1] 5更新 minDist[3] minDist[1] 5 0 5 5以上是对所有边进行一次松弛之后的结果。对所有边松弛一次相当于计算 起点到达 与起点一条边相连的节点 的最短距离。上面的距离中我们得到里 起点达到 与起点一条边相邻的节点2 和 节点3 的最短距离分别是 minDist[2] 和 minDist[3]。再回归刚刚的问题需要对所有边松弛几次才能得到 起点节点1 到终点节点6的最短距离呢节点数量为n那么起点到终点最多是 n-1 条边相连。那么无论图是什么样的边是什么样的顺序我们对所有边松弛 n-1 次 就一定能得到 起点到达 终点的最短距离。其实也同时计算出了起点 到达 所有节点的最短距离因为所有节点与起点连接的边数最多也就是 n-1 条边。Bellman_ford 的核心算法思路共有两个关键点“松弛”究竟是个啥为什么要对所有边松弛 n - 1 次 n为节点个数importjava.util.*;publicclassMain{staticclassEdge{intfrom;intto;intval;publicEdge(intfrom,intto,intval){this.fromfrom;this.toto;this.valval;}}publicstaticvoidmain(String[]args){ScannerscnewScanner(System.in);intnsc.nextInt();intmsc.nextInt();ListEdgeedgesnewArrayList();for(inti0;im;i){intfromsc.nextInt();inttosc.nextInt();intvalsc.nextInt();edges.add(newEdge(from,to,val));}int[]mindistnewint[n1];Arrays.fill(mindist,Integer.MAX_VALUE);mindist[1]0;for(inti1;in;i){//松弛n-1次for(Edgeedge:edges){if(mindist[edge.from]!Integer.MAX_VALUE(mindist[edge.from]edge.val)mindist[edge.to]){mindist[edge.to]mindist[edge.from]edge.val;}}}if(mindist[n]Integer.MAX_VALUE){System.out.println(unconnected);}else{System.out.println(mindist[n]);}}}
基于Matlab Simulink的微电网逆变并网系统仿真研究:VSG虚拟同步机与下垂控制策略的优化 基于Matlab/Simulink搭建微电网逆变并网系统: 1.采用VSG虚拟同步机控制策略 2.采用下垂控制策略 仿真波形较好最近在实验室折腾微电网并网系统,顺手用Matlab/Simulink搭了个支持两种经典控制策略的模型。两种方案都跑出了丝滑的仿真波形,特别… 2026/5/17 9:26:17
计算机毕业设计springboot社区文化服务管理系统 基于SpringBoot的社区文化活动数字化运营平台 SpringBoot驱动的居民文化服务与资源协同管理系统 计算机毕业设计springboot社区文化服务管理系统4c192vwy(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。随着城市化进程的加速推进和居民精神文化需求的日益增长,社区… 2026/7/2 19:36:07
CKEditor如何实现Ctrl+V粘贴图片并自动上传服务器? 山东某国企项目需求实现记录:基于CKEditor4的Word/微信内容集成方案 一、需求分析与技术选型 核心需求: 编辑器插件需支持: Word粘贴(保留格式图片自动上传)Word/Excel/PPT/PDF导入(保留格式图片ÿ… 2026/5/17 9:26:16
卫星安全攻防指南:从地面站渗透到轨道攻击的实战解析 1. 项目概述:当“太空”成为攻防新战场最近几年,我身边不少做安全研究的朋友,话题都开始从传统的Web渗透、内网漫游,逐渐转向了一些更“高远”的领域。其中一个绕不开的焦点,就是太空与卫星安全。这听起来像是科幻电影… 2026/7/5 10:13:06
固态硬盘核心技术解析与选购指南 1. 固态硬盘为何成为升级首选?2006年,当三星推出首款面向消费市场的32GB固态硬盘时,其售价高达数千美元,容量却不及当时主流机械硬盘的十分之一。十五年后的今天,一块1TB固态硬盘的价格已降至300元人民币左右ÿ… 2026/7/5 10:13:06
2026年移动与服务器处理器架构解析 1. 2026年移动处理器格局解析 2026年的移动处理器市场呈现出前所未有的技术分化态势,AMD与Intel两大巨头在笔记本CPU领域的竞争已从单纯的性能比拼,演变为架构设计哲学的根本差异。这场较量背后,反映的是对移动计算场景的深度理解与技术创新。… 2026/7/5 10:09:04
BK7259芯片解析:边缘AI与多媒体处理的低功耗方案 1. BK7259芯片深度解析:边缘AI与多媒体处理的瑞士军刀 在智能家居和工业物联网设备爆发式增长的今天,开发者们面临着一个核心矛盾:既要实现复杂的本地AI推理和多媒体处理,又要严格控制功耗和成本。博通集成推出的BK7259芯片&#… 2026/7/5 10:09:04
西门子Smart200 PLC实现电机恒速控制的技术解析 1. Smart200 PLC与电机恒速控制基础西门子S7-200 Smart系列PLC作为中小型自动化项目的经典选择,在电机控制领域有着广泛应用。要实现电机恒速运行,我们需要先理解几个核心概念:电机恒速控制的本质是通过实时调节输出功率来抵消负载变化带来的… 2026/7/5 10:07:04
Liberty格式在RTL综合中的关键作用与实现解析 1. Liberty格式在RTL综合中的核心地位 Liberty格式(.lib)是芯片设计流程中不可或缺的时序库描述标准,它定义了标准单元、IO单元和特殊功能单元的时序、功耗及功能特性。作为RTL综合阶段的关键输入文件,Liberty文件的质量直接决定了… 2026/7/5 10:07:04
6个月转型AI工程师:实战路径与核心技能 1. 项目概述:6个月转型AI工程师的可行性路径在2023年大模型技术爆发的背景下,AI工程师岗位需求同比增长217%(LinkedIn数据)。不同于传统算法工程师需要3-5年培养周期,现代AI工程师更侧重工程化落地能力。我在硅谷科技公… 2026/7/5 0:01:32
TPAFE0808与PIC18F87K22的多通道信号采集方案 1. 项目背景与核心需求在工业自动化、医疗设备和科研仪器等领域,多通道信号采集与系统监测是基础且关键的技术需求。传统方案往往面临通道数量不足、信号调理复杂、系统集成度低等问题。TPAFE0808作为一款8通道模拟前端芯片,与PIC18F87K22微控制器的组合… 2026/7/5 0:01:32
STC3115与PIC18LF26K80构建高精度电池管理系统 1. STC3115与PIC18LF26K80在电池管理系统中的核心价值在现代电子设备中,电池管理系统(BMS)的重要性不亚于设备的核心处理器。STC3115作为一款高精度电池电量监测IC,与PIC18LF26K80微控制器的组合,构成了一个既能精确监控又能智能管理的完整解… 2026/7/5 0:05:36
6个月转型AI工程师:实战路径与核心技能 1. 项目概述:6个月转型AI工程师的可行性路径在2023年大模型技术爆发的背景下,AI工程师岗位需求同比增长217%(LinkedIn数据)。不同于传统算法工程师需要3-5年培养周期,现代AI工程师更侧重工程化落地能力。我在硅谷科技公… 2026/7/5 0:01:32
TPAFE0808与PIC18F87K22的多通道信号采集方案 1. 项目背景与核心需求在工业自动化、医疗设备和科研仪器等领域,多通道信号采集与系统监测是基础且关键的技术需求。传统方案往往面临通道数量不足、信号调理复杂、系统集成度低等问题。TPAFE0808作为一款8通道模拟前端芯片,与PIC18F87K22微控制器的组合… 2026/7/5 0:01:32
STC3115与PIC18LF26K80构建高精度电池管理系统 1. STC3115与PIC18LF26K80在电池管理系统中的核心价值在现代电子设备中,电池管理系统(BMS)的重要性不亚于设备的核心处理器。STC3115作为一款高精度电池电量监测IC,与PIC18LF26K80微控制器的组合,构成了一个既能精确监控又能智能管理的完整解… 2026/7/5 0:05:36