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

算法模板(Java版)_图的最短路径

@ZZHow(ZZHow1024)

图的最短路径问题:

  • 单源最短路
    • 所有边权都是正数
      • 朴素 Dijkstra 算法 O(n2)O(n ^ 2)O(n2)
      • 堆优化版 Dijkstra 算法 O(m∗log2n)O(m*log_2 n)O(mlog2n)
    • 存在负权边
      • Bellman-Ford 算法 O(n∗m)O(n * m)O(nm)
      • SPFA 算法 一般O(m),最坏O(n∗m)一般 O(m),最坏 O(n * m)一般O(m),最坏O(nm)
  • 多源汇最短路
    • Floyd 算法 O(n3)O(n ^ 3)O(n3)

朴素 Dijkstra

迪杰斯特拉算法采用的是一种贪心的策略。进行 n 次迭代去确定每个点到起点的最小值,最后输出的终点的即为我们要找的最短路的距离。

  • 例题:AcWing 849. Dijkstra求最短路 I
import java.util.Scanner;public class Main {static final int N = 510;static long[][] g = new long[N][N];static long[] dist = new long[N];static boolean[] st = new boolean[N];public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();for (int i = 0; i <= n; i++)for (int j = 0; j <= n; j++)g[i][j] = Integer.MAX_VALUE;while (m-- != 0) {int a = scanner.nextInt();int b = scanner.nextInt();int c = scanner.nextInt();g[a][b] = Math.min(g[a][b], c);}System.out.println(dijkstra(n));}public static long dijkstra(int n) {for (int i = 0; i <= n; i++)dist[i] = Integer.MAX_VALUE;dist[1] = 0;for (int i = 0; i < n; i++) {int t = -1;for (int j = 1; j <= n; j++)if (!st[j] && (t == -1 || dist[t] > dist[j]))t = j;st[t] = true;for (int j = 1; j <= n; j++)dist[j] = Math.min(dist[j], dist[t] + g[t][j]);}if (dist[n] == Integer.MAX_VALUE)return -1;elsereturn dist[n];}
}

堆优化版 Dijkstra

对朴素版 Dijkstra 进行优化,在时间复杂度最高的寻找距离最短的点 O(n2)O(n^2)O(n2) 时可以使用小根堆优化,Java 语言可使用优先队列(PriorityQueue),配合自定义的 Pair 类实现。

  • 例题:AcWing 850. Dijkstra求最短路 II
import java.util.*;public class Main {static final int N = 1000010;static int idx = 0;static int[] h = new int[N];static int[] e = new int[N];static int[] w = new int[N];static int[] ne = new int[N];static long[] dist = new long[N];static boolean[] st = new boolean[N];public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();Arrays.fill(h, -1);while (m-- != 0) {int a = scanner.nextInt();int b = scanner.nextInt();int c = scanner.nextInt();add(a, b, c);}System.out.println(dijkstra(n));}public static void add(int a, int b, int c) {e[idx] = b;w[idx] = c;ne[idx] = h[a];h[a] = idx++;}public static long dijkstra(int n) {Arrays.fill(dist, Integer.MAX_VALUE);dist[1] = 0;Queue<Pair> heap = new PriorityQueue<>();heap.add(new Pair(0L, 1));while (!heap.isEmpty()) {Pair t = heap.poll();long distance = t.first;int ver = t.second;if (st[ver])continue;st[ver] = true;for (int i = h[ver]; i != -1; i = ne[i]) {int j = e[i];if (dist[j] > distance + w[i]) {dist[j] = distance + w[i];heap.add(new Pair(dist[j], j));}}}if (dist[n] == Integer.MAX_VALUE)return -1;elsereturn dist[n];}
}class Pair implements Comparable<Pair> {public long first;public int second;public Pair() {}public Pair(long a, int b) {this.first = a;this.second = b;}@Overridepublic int compareTo(Pair o) {return (int)Math.signum(this.first - o.first);}
}

bellman-ford

迭代 nnn 次,每次循环所有边(a,b,w)(a, b, w)(a,b,w),更新路径:dist[b] = min(dist[b], dist[a] + w);(松弛操作)。全部操作完后满足三角不等式:dist[b]≤dist[a]+wdist[b] ≤ dist[a] + wdist[b]dist[a]+w

  • 例题:AcWing 853. 有边数限制的最短路
import java.util.*;public class Main {public static int n;public static int m;public static int k;public static int[] dist;public static int[] backup;public static Edge[] edge;public static final int MAX = 0x3f3f3f3f;public static void main(String[] args) {Scanner scanner= new Scanner(System.in);n = scanner.nextInt();m = scanner.nextInt();k = scanner.nextInt();dist = new int[n + 10];Arrays.fill(dist, MAX);dist[1] = 0;edge = new Edge[m + 10];for (int i = 0; i < m; i++) {int a = scanner.nextInt();int b = scanner.nextInt();int w = scanner.nextInt();edge[i] = new Edge(a, b, w);}int t = bellmanFord();if (t > MAX >> 1)System.out.println("impossible");elseSystem.out.println(t);}public static int bellmanFord() {for (int i = 0; i < k; i++) {backup = Arrays.copyOf(dist, dist.length);for (int j = 0; j < m; j++) {int a = edge[j].a;int b = edge[j].b;int w = edge[j].w;dist[b] = Math.min(dist[b], backup[a] + w);}}return dist[n];}
}class Edge {public int a;public int b;public int w;public Edge(int a, int b, int w) {this.a = a;this.b = b;this.w = w;}
}

SPFA

针对 bellman-ford 算法的 dist[b] = Math.min(dist[b], backup[a] + w); 使用队列进行优化。

  • 例题:AcWing 851. spfa求最短路
  • 例题:AcWing 852. spfa判断负环
import java.util.*;public class Main {public static int n;public static int m;public static int[] h;public static int[] w;public static int[] e;public static int[] ne;public static int idx;public static int[] dist;public static boolean[] st;public static final int MAX = 0x3f3f3f3f;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);n = scanner.nextInt();m = scanner.nextInt();h = new int[n + 10];w = new int[m + 10];e = new int[m + 10];ne = new int[m + 10];dist = new int[n + 10];st = new boolean[n + 10];Arrays.fill(h, -1);while (m-- != 0) {int a = scanner.nextInt();int b = scanner.nextInt();int c = scanner.nextInt();add(a, b, c);}int t = spfa();if (t > MAX >> 1)System.out.println("impossible");elseSystem.out.println(t);}public static void add(int a, int b, int c) {e[idx] = b;w[idx] = c;ne[idx] = h[a];h[a] = idx++;}public static int spfa() {Arrays.fill(dist, MAX);dist[1] = 0;Queue<Integer> q = new ArrayDeque<>();q.add(1);st[1] = true;while (!q.isEmpty()) {int t = q.poll();st[t] = false;for (int i = h[t]; i != -1; i = ne[i]) {int j = e[i];if (dist[j] > dist[t] + w[i]) {dist[j] = dist[t] + w[i];if (!st[j]) {q.add(j);st[j] = true;}}}}return dist[n];}
}

Floyd

基于动态规划。枚举 k,i,jk, i, jk,i,j 更新路径:d(i, j) = min(d(i, j), d(i, k) + d(k, j));

  • 例题:AcWing 854. Floyd求最短路
import java.util.*;public class Main {public static int n;public static int m;public static int k;public static int[][] d;public static final int MAX = 0x3f3f3f3f;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);n = scanner.nextInt();m = scanner.nextInt();k = scanner.nextInt();d = new int[n + 10][n + 10];for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)if (i == j)d[i][j] = 0;elsed[i][j] = MAX;while (m-- != 0) {int a = scanner.nextInt();int b = scanner.nextInt();int w = scanner.nextInt();d[a][b] = Math.min(d[a][b], w);}floyd();while (k-- != 0) {int a = scanner.nextInt();int b = scanner.nextInt();if (d[a][b] > MAX >> 1)System.out.println("impossible");elseSystem.out.println(d[a][b]);}}public static void floyd() {for (int k = 1; k <= n; k++)for (int i = 1; i <= n; i++)for (int j = 1; j <= n; j++)d[i][j] = Math.min(d[i][j], d[i][k] + d[k][j]);}
}

文章转载自:

http://yCuuTkz6.rnrfs.cn
http://EzvDw1rM.rnrfs.cn
http://hm7DYuDc.rnrfs.cn
http://vt2v8k16.rnrfs.cn
http://SfbBOR2U.rnrfs.cn
http://8gBwLID6.rnrfs.cn
http://2mGNiRVe.rnrfs.cn
http://DJE8BnfK.rnrfs.cn
http://UDk4MRPq.rnrfs.cn
http://lqwn6A7P.rnrfs.cn
http://BPUfwf0w.rnrfs.cn
http://I1m2O3yU.rnrfs.cn
http://lFm2D1lG.rnrfs.cn
http://3s4KeClH.rnrfs.cn
http://su2mQJ9Q.rnrfs.cn
http://wjXxSfij.rnrfs.cn
http://sBzck58t.rnrfs.cn
http://2vpIMdZN.rnrfs.cn
http://HwgJbpD0.rnrfs.cn
http://iRLqeQEO.rnrfs.cn
http://0w1NzwtN.rnrfs.cn
http://u9LZtHm1.rnrfs.cn
http://kPxysVSv.rnrfs.cn
http://8phyBmFs.rnrfs.cn
http://vK8K7x3Y.rnrfs.cn
http://cr1tONV8.rnrfs.cn
http://JB4hfo2K.rnrfs.cn
http://1SFiBFrh.rnrfs.cn
http://3MkIClrx.rnrfs.cn
http://gb1go7nD.rnrfs.cn
http://www.dtcms.com/a/369606.html

相关文章:

  • 【开题答辩全过程】以 基于Springboot电脑维修平台整合系统的设计与实现为例,包含答辩的问题和答案
  • MySQL慢查询优化策略
  • 批量生成角色及动画-角色动画转化为mixamo骨骼(二)
  • 再读强化学习(动态规划)
  • 安装Codex(需要用npm)
  • 显示调试工具
  • Dify-CHATflow案例
  • 探索Xilinx GTH收发器掉电与回环功能
  • 数据结构初阶:树的相关性质总结
  • whl编译命令作用解释
  • 如何在序列水平上简单分析一个新蛋白质序列(novel protein sequence)
  • 苹果手机ios系统下载了.apk文件程序怎么安装?
  • 认知篇#11:计算机视觉研究领域的大致分类
  • 如何高效比对不同合同版本差异,避免法律风险?
  • 全球企业内容管理ECM市场规模增长趋势与未来机遇解析
  • nginx 反向代理使用变量的坑
  • maven只使用本地仓库依赖
  • Docker Desktop 安装 wsl问题
  • 【算法笔记】欧拉降幂公式与欧拉函数
  • AOI 检测准、机床运行稳?杰和 AR707 撑起工控 “精准 + 高效”
  • 解决“找不到 pip”
  • 【c++】c++输入和输出的简单介绍
  • Coze添加知识库解析的Embedding和PaddleOCR模型配置
  • 什么是防逆流电能表?深度解析如何实现防逆流
  • 孙宇晨钱包被列入黑名单,WLFI代币价格暴跌引发中心化争议
  • 第七章 Cesium 3D 粒子烟花效果案例解析:从原理到完整代码
  • 【110】基于51单片机金属探测器【Proteus仿真+Keil程序+报告+原理图】
  • (双指针)LeetCode 209 长度最小的子数组+3 无重复字符的最长子串
  • 技术面:Java并发(线程池、ForkJoinPool)
  • 2026秋招Leetcode刷题记录