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

day55 代码随想录算法训练营 图论专题9

1 今日打卡

dijkstra堆优化版 47. 参加科学大会(第六期模拟笔试)

bellman_ford算法 94. 城市间货物运输 I

2 dijkstra堆优化版

2.1 思路

数据结构准备:用邻接表存储图的边信息,用优先队列(小顶堆)快速找到当前距离起点最近的未访问节点,用数组记录起点到各节点的最短距离、访问状态。
初始化:起点到自身的距离设为 0,其余节点初始化为无穷大;优先队列加入起点(距离为 0)。
核心循环:
从优先队列取出当前距离起点最近的节点,标记为已访问。
遍历该节点的所有邻接边,更新邻接节点的最短距离(若通过当前节点到达邻接节点的路径更短)。
把更新后的邻接节点加入优先队列,继续循环直到队列为空。
结果输出:若终点距离仍为无穷大,说明无法到达;否则输出最短距离。

2.2 实现代码

import java.util.*; // 定义边的类:存储邻接顶点和边的权重 class Edge { int to; // 边指向的邻接顶点编号 int val; // 这条边的权重(长度) // 构造方法:初始化边的指向和权重 Edge(int to, int val) { this.to = to; this.val = val; } } // 自定义优先队列的比较器:按Pair的第二个值(距离)升序排列(小顶堆) class MyComparison implements Comparator<Pair<Integer, Integer>> { @Override public int compare(Pair<Integer, Integer> lhs, Pair<Integer, Integer> rhs) { // 比较两个Pair的第二个元素(距离),保证优先队列弹出距离最小的节点 return Integer.compare(lhs.second, rhs.second); } } // 自定义Pair类:存储<节点编号, 起点到该节点的距离> class Pair<U, V> { public final U first; // 第一个元素:节点编号 public final V second; // 第二个元素:起点到该节点的距离 // 构造方法:初始化Pair的两个元素 public Pair(U first, V second) { this.first = first; this.second = second; } } public class Main { public static void main(String[] args) { // 1. 输入处理:读取图的节点数n和边数m Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); // 节点总数(节点编号从1到n) int m = scanner.nextInt(); // 边的总数 // 2. 构建邻接表:存储图的边信息(grid[i]存储节点i的所有出边) List<List<Edge>> grid = new ArrayList<>(n + 1); // 初始化邻接表:节点编号从1开始,所以初始化n+1个空列表 for (int i = 0; i <= n; i++) { grid.add(new ArrayList<>()); } // 3. 读取每条边的信息,填充邻接表 for (int i = 0; i < m; i++) { int p1 = scanner.nextInt(); // 边的起点 int p2 = scanner.nextInt(); // 边的终点 int val = scanner.nextInt();// 边的权重 // 向p1的出边列表中添加一条指向p2、权重为val的边 grid.get(p1).add(new Edge(p2, val)); } // 4. 定义起点和终点:起点固定为1,终点固定为n int start = 1; // 最短路径的起点 int end = n; // 最短路径的终点 // 5. 初始化最短距离数组:minDist[i]表示起点到节点i的最短距离 int[] minDist = new int[n + 1]; // 初始化为无穷大(表示初始时无法到达) Arrays.fill(minDist, Integer.MAX_VALUE); // 6. 初始化访问状态数组:visited[i]为true表示节点i已处理完毕 boolean[] visited = new boolean[n + 1]; // 7. 初始化优先队列:存储<节点编号, 起点到该节点的距离>,按距离升序排列 PriorityQueue<Pair<Integer, Integer>> pq = new PriorityQueue<>(new MyComparison()); // 8. 起点初始化:起点到自身的距离为0,加入优先队列 pq.add(new Pair<>(start, 0)); minDist[start] = 0; // 9. Dijkstra核心循环:处理所有节点 while (!pq.isEmpty()) { // 9.1 取出当前距离起点最近的节点(优先队列顶) Pair<Integer, Integer> cur = pq.poll(); int curNode = cur.first; // 当前节点编号 int curDist = cur.second; // 起点到当前节点的距离 // 9.2 如果该节点已处理过,直接跳过(避免重复处理) if (visited[curNode]) continue; // 9.3 标记该节点为已访问(处理完毕,最短距离已确定) visited[curNode] = true; // 9.4 遍历当前节点的所有出边,更新邻接节点的最短距离 for (Edge edge : grid.get(curNode)) { int nextNode = edge.to; // 邻接节点编号 int edgeVal = edge.val; // 当前边的权重 // 条件:邻接节点未访问 + 起点到当前节点的距离 + 边权重 < 起点到邻接节点的当前最短距离 if (!visited[nextNode] && minDist[curNode] != Integer.MAX_VALUE && minDist[curNode] + edgeVal < minDist[nextNode]) { // 更新邻接节点的最短距离 minDist[nextNode] = minDist[curNode] + edgeVal; // 将更新后的邻接节点加入优先队列(可能重复加入,但不影响,因为已访问的会跳过) pq.add(new Pair<>(nextNode, minDist[nextNode])); } } } // 10. 输出结果 if (minDist[end] == Integer.MAX_VALUE) { // 终点距离仍为无穷大,说明无法到达 System.out.println(-1); } else { // 输出起点到终点的最短距离 System.out.println(minDist[end]); } // 关闭扫描器(规范写法) scanner.close(); } }

3 bell_ford算法

3.1 思路

数据结构准备:用邻接表存储图的边信息,用普通队列(而非优先队列)存储待松弛的节点,用数组记录起点到各节点的最短距离、节点是否在队列中(避免重复入队)。
初始化:起点到自身的距离设为 0,其余节点初始化为无穷大;起点加入队列并标记为 “在队列中”。
核心循环(松弛操作):
从队列取出节点,取消其 “在队列中” 的标记。
遍历该节点的所有邻接边,若通过当前节点到达邻接节点的路径更短,则更新邻接节点的最短距离。
若邻接节点不在队列中,将其加入队列并标记,继续循环直到队列为空。
结果输出:若终点距离仍为无穷大,说明无法到达;否则输出最短距离。

3.2 实现代码

import java.util.*; public class Main { // 定义边的内部类:存储边的终点和权重 static class Link { int to; // 边指向的邻接节点编号 int val; // 这条边的权重(长度) // 构造方法:初始化边的终点和权重 public Link(int to, int val) { this.to = to; this.val = val; } } public static void main(String[] args) { // 1. 输入处理:读取节点数n和边数m Scanner sc = new Scanner(System.in); int n = sc.nextInt(), m = sc.nextInt(); // n=节点总数(1~n),m=边总数 // 2. 构建邻接表:存储图的边信息(map[i]存储节点i的所有出边) List<List<Link>> map = new ArrayList<>(); // 初始化邻接表:节点编号从1开始,所以初始化n+1个空列表 for (int i = 0; i <= n; i++) { map.add(new ArrayList<>()); } // 3. 读取每条边的信息,填充邻接表 for (int i = 0; i < m; i++) { int from = sc.nextInt(); // 边的起点 int to = sc.nextInt(); // 边的终点 int val = sc.nextInt(); // 边的权重 // 向起点from的出边列表中添加一条指向to、权重为val的边 map.get(from).add(new Link(to, val)); } // 4. 初始化最短距离数组:minDist[i]表示起点(1)到节点i的最短距离 int[] minDist = new int[n + 1]; // 初始化为无穷大(表示初始时无法到达) Arrays.fill(minDist, Integer.MAX_VALUE); minDist[1] = 0; // 起点(1)到自身的距离为0 // 5. 初始化队列标记数组:isInQueue[i]为true表示节点i已在队列中(避免重复入队) boolean[] isInQueue = new boolean[n + 1]; Queue<Integer> que = new LinkedList<>(); // 存储待松弛的节点 que.add(1); // 起点加入队列 isInQueue[1] = true; // 标记起点在队列中 // 6. SPFA核心循环:松弛所有可优化的边 while (!que.isEmpty()) { int cur = que.poll(); // 取出队列头部的节点(当前待处理节点) isInQueue[cur] = false; // 取消该节点的队列标记(允许后续重新入队) // 遍历当前节点的所有出边,进行松弛操作 for (Link link : map.get(cur)) { int to = link.to; // 邻接节点编号 int val = link.val; // 当前边的权重 // 松弛条件:起点到cur的距离 + 边权重 < 起点到to的当前最短距离 // 补充:minDist[cur] != Integer.MAX_VALUE 避免无穷大+数值溢出 if (minDist[cur] != Integer.MAX_VALUE && minDist[cur] + val < minDist[to]) { minDist[to] = minDist[cur] + val; // 更新最短距离 // 若邻接节点不在队列中,加入队列并标记 if (!isInQueue[to]) { que.add(to); isInQueue[to] = true; } } } } // 7. 输出结果 if (minDist[n] == Integer.MAX_VALUE) { // 终点n的距离仍为无穷大,说明无法到达 System.out.println("unconnected"); } else { // 输出起点1到终点n的最短距离 System.out.println(minDist[n]); } sc.close(); // 关闭扫描器(规范写法) } }
http://www.jsqmd.com/news/500389/

相关文章:

  • 软件质量概念、八大质量模型特征、影响质量的因素
  • LLM 节点调参-AI不再胡扯
  • QtCreator开发软件使用小技巧
  • CD147(分化簇147):作用机制、上市药物与未来研发趋势
  • JavaScript基础课程十三、ES6+ 核心语法(三)——数组与对象高级方法
  • 2025年年终总结之17.教育之文化的意义
  • LangChain4j AI Services 深度解析:声明式 API 与接口驱动开发
  • 企业私域运营全指南:从 0 到 10 万用户,可复制的全链路实操手册
  • 部署EasyVoice实现文字转语音
  • 2026山西继承纠纷有名律师选购要注意什么 - myqiye
  • 九、硬件要求
  • localStorage vs sessionStorage
  • 伴侣间的信任感被破坏后,如何重建与修复?
  • ENVI直接打开Landsat的C2L2数据(landsat5/8/9)
  • Linux传输层TCP,UDP相关内容
  • SEO_避开这些常见误区,让你的SEO事半功倍(435 )
  • 聊聊银川面部祛痣专业机构,费用大概多少钱? - 工业推荐榜
  • 京东e卡回收哪家强?深度解析热门回收渠道优劣 - 团团收购物卡回收
  • 觉得360讨厌?想卸载?那是你不会用
  • openclaw[龙虾]禁用版本升级提示
  • UL4200A认证全流程:从申请到证书获取
  • 网络编程第一天学习笔记(重点:UDP 协议)
  • 【全网唯一】第一篇 我要创造一门全新中文编程语言——华夏本源语言
  • 2026年壁挂新风系统选购指南:8款主流品牌深度横评 - 新闻快传
  • 探讨2026年深圳GH4169镍基合金钢板性价比,哪家更优? - 工业品网
  • 讲讲GH4169镍基合金费用,深圳地区哪家收费合理? - 工业品牌热点
  • 2026-3-18
  • neo4j知识图谱+大模型教育应用赋能教育技术学专业
  • 注意!选择京东e卡回收渠道前需要了解的3个技巧 - 团团收购物卡回收
  • Anaconda被误删后抢救手册