蓝桥杯 Java B 组之最短路径算法(Dijkstra、Floyd-Warshall)

news/2025/2/25 22:45:27/

Day 2:最短路径算法(Dijkstra、Floyd-Warshall)


📖 一、最短路径算法简介

最短路径问题是图论中的经典问题,主要用于求解 单源最短路径多源最短路径。在实际应用中,最短路径广泛应用于 导航系统、网络路由、任务调度 等场景。

📌 最短路径算法分类

算法适用场景时间复杂度
Dijkstra单源最短路径(无负权)O((V+E) logV)(使用优先队列优化)
Floyd-Warshall多源最短路径O(V³)
Bellman-Ford处理负权边的单源最短路径O(VE)

📖 二、Dijkstra 算法(单源最短路径)

适用范围

  • 适用于无负权边单源最短路径问题。
  • 主要思想是:使用 贪心 + 优先队列 找到当前最短的路径

🔹 1. 题目:网络延迟时间(Leetcode 743)

题目描述: 给定 n 个节点的有向图,边 times[i] = (u, v, w) 表示从 uv 的边权为 w。从源点 k 发送信号,计算所有节点都收到信号的最短时间,若无法到达所有节点,返回 -1

示例

输入: times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
输出: 2

🔹 2. 思路

  • 使用 Dijkstra 算法,**优先队列(最小堆)**优化时间复杂度。
  • 维护 dist[] 数组,dist[i] 代表从 ki 的最短路径。
  • 使用 最小堆(PriorityQueue) 维护当前最短路径的节点,每次弹出最短路径节点,更新其邻接点。

🔹 3. 代码实现

import java.util.*;public class DijkstraNetworkDelay {public int networkDelayTime(int[][] times, int n, int k) {// 图的邻接表Map<Integer, List<int[]>> graph = new HashMap<>();for (int[] edge : times) {graph.putIfAbsent(edge[0], new ArrayList<>());graph.get(edge[0]).add(new int[]{edge[1], edge[2]});}// 最小堆(按路径权值排序)PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));pq.offer(new int[]{k, 0}); // 从源点 k 开始Map<Integer, Integer> dist = new HashMap<>();while (!pq.isEmpty()) {int[] cur = pq.poll();int node = cur[0], time = cur[1];if (dist.containsKey(node)) continue; // 已访问dist.put(node, time);if (!graph.containsKey(node)) continue;for (int[] next : graph.get(node)) {int neighbor = next[0], weight = next[1];if (!dist.containsKey(neighbor)) {pq.offer(new int[]{neighbor, time + weight});}}}if (dist.size() < n) return -1; // 说明有节点不可达return Collections.max(dist.values()); // 返回最长的最短路径}public static void main(String[] args) {DijkstraNetworkDelay solution = new DijkstraNetworkDelay();int[][] times = {{2,1,1},{2,3,1},{3,4,1}};int n = 4, k = 2;System.out.println(solution.networkDelayTime(times, n, k)); // 输出 2}
}

🔹 4. 代码讲解

  1. 构建邻接表:用 Map<Integer, List<int[]>> 存储 邻接节点和权重
  2. 使用优先队列(最小堆):每次取出当前路径最短的节点进行扩展,更新邻接点的最短路径。
  3. 利用 dist[] 数组:记录从 k 到各个节点的最短路径。
  4. 时间复杂度
    • O((V+E) logV)(优先队列优化)。
    • 其中 V 是顶点数,E 是边数。

📖 三、Floyd-Warshall 算法(多源最短路径)

适用范围

  • 适用于多源最短路径问题。
  • 允许 负权边(但不能有负权环)。
  • 主要思想是:动态规划,每次考虑是否经过某个中间点 k 能让路径更短

🔹 1. 题目:2019 省赛 - 迷宫

题目描述: 给定一个 n × n 的迷宫,1 表示墙,0 表示可通行。求从起点 (0,0) 到终点 (n-1,n-1)最短路径

输入示例

4
0 0 1 0
1 0 1 0
1 0 0 0
1 1 1 0

输出

5

(路径 [(0,0) -> (1,1) -> (2,1) -> (2,2) -> (2,3) -> (3,3)]


🔹 2. 思路

  1. 转换为图问题:迷宫是一个 n × n 的无向图,连通区域是 可通行的 0
  2. 使用 Floyd-Warshall 算法
    • dist[i][j] 存储 (0,0)(i,j) 的最短路径
    • grid[i][j] == 1,设 dist[i][j] = ∞(墙)。
    • dist[i][j] = min(dist[i][j], dist[k][m] + 1),其中 (k,m) 是邻居。

🔹 3. 代码实现

import java.util.*;public class FloydWarshallMaze {static final int INF = 10000; // 设定一个较大的数表示不可达static int[][] dist;static int[][] directions = {{1,0}, {0,1}, {-1,0}, {0,-1}}; // 上下左右四个方向public static int shortestPath(int[][] maze) {int n = maze.length;dist = new int[n][n];// 初始化距离数组for (int i = 0; i < n; i++) {Arrays.fill(dist[i], INF);}dist[0][0] = 0; // 起点// Floyd-Warshall 核心算法for (int k = 0; k < n; k++) { // 中间点for (int i = 0; i < n; i++) { // 起点for (int j = 0; j < n; j++) { // 终点if (maze[i][j] == 0) {for (int[] dir : directions) {int x = i + dir[0], y = j + dir[1];if (x >= 0 && x < n && y >= 0 && y < n && maze[x][y] == 0) {dist[x][y] = Math.min(dist[x][y], dist[i][j] + 1);}}}}}}return dist[n-1][n-1] == INF ? -1 : dist[n-1][n-1];}public static void main(String[] args) {int[][] maze = {{0, 0, 1, 0},{1, 0, 1, 0},{1, 0, 0, 0},{1, 1, 1, 0}};System.out.println(shortestPath(maze)); // 输出 5}
}

📖 四、总结

Dijkstra vs Floyd-Warshall

算法适用范围时间复杂度
Dijkstra单源最短路径O((V+E) logV)
Floyd-Warshall多源最短路径O(V³)

🎯 练习建议

  • 熟练掌握 Dijkstra + 优先队列优化(最小堆 PriorityQueue)。
  • 理解 Floyd-Warshall 多源最短路径的动态规划思想


http://www.ppmy.cn/news/1574910.html

相关文章

生活教练项目_Trae

XMXALifeCoach - 个人成长辅导网站 网址: https://github.com/zhangxiaomeng1/XMXALifeCoach 项目简介 这是一个基于DeepSeek R1 API开发的个人成长辅导网站。通过与AI进行对话&#xff0c;用户可以获得个性化的建议和指导&#xff0c;帮助个人成长。 技术架构 前端&#xff1a…

overflow-x: auto 使用鼠标实现横向滚动,区分触摸板和鼠标滚动事件的方法

假设一个 div 的滚动只设置了 overflow-x: auto 我们发现使用鼠标的滚轮是无法左右滚动的&#xff0c;但是使用笔记本电脑的触摸板&#xff0c;或者在移动设备上是可以滚动的。所以我们需要兼容一下鼠标的横向滚动功能。 我们可以监控 wheel 事件&#xff0c;然后根据位置来计…

让Word插上AI的翅膀:如何把DeepSeek装进Word

在日常办公中&#xff0c;微软的Word无疑是我们最常用的文字处理工具。无论是撰写报告、编辑文档&#xff0c;还是整理笔记&#xff0c;Word都能胜任。然而&#xff0c;随着AI技术的飞速发展&#xff0c;尤其是DeepSeek的出现&#xff0c;我们的文字编辑方式正在发生革命性的变…

python-leetcode 42.验证二叉搜索树

题目&#xff1a; 给定二叉树的根节点root,判断是否是一个有效二叉搜索树 有效二叉搜索树&#xff1a; 1.节点的左子树只包含小于当前节点的树 2.节点的右子树只包含大于当前节点的树 3.所有左子树和右子树自身必须也是二叉搜索树 方法一&#xff1a;递归 如果该二叉树的…

DeepSeek 15天指导手册——从入门到精通 PDF(附下载)

DeepSeek使用教程系列--DeepSeek 15天指导手册——从入门到精通pdf下载&#xff1a; https://pan.baidu.com/s/1PrIo0Xo0h5s6Plcc_smS8w?pwd1234 提取码: 1234 或 https://pan.quark.cn/s/2e8de75027d3 《DeepSeek 15天指导手册——从入门到精通》以系统化学习路径为核心&…

SpringBoot+Vue+微信小程序的猫咖小程序平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当下这个高速发展的时代&#xff0c;网络科技正以令人惊叹的速度不断迭代更新。从 5G …

七.智慧城市数据治理平台架构

一、整体架构概览 智慧城市数据治理平台架构描绘了一个全面的智慧城市数据治理平台&#xff0c;旨在实现城市数据的统一管理、共享和应用&#xff0c;为城市运行、管理和决策提供数据支撑。整体架构呈现出分层、模块化、集约化的特点&#xff0c;并强调数据安全和标准规范。 智…

小迪安全23-php后台模块

cookie技术 cookie就是身份验证表示&#xff0c;通过cookie好区分每个用户的个人数据和权限&#xff0c;第一次登陆之后正常的网站都会赋予一个cookie 写写一个后台界面&#xff0c;直接让ai去写就可以 然后自己需要的提交方式&#xff0c;和表单值自己修改即可 生成cookie的…