文章目录

  • 贝尔曼-福特算法(Bellman-Ford)
    • 简介
    • 算法思想
    • 算法执行过程
    • 应用
      • 题目描述
      • 分析
      • 代码
  • LeetCode 787. K 站中转内最便宜的航班
    • 题目描述
    • Bellman Ford + 邻接矩阵
  • Reference

贝尔曼-福特算法(Bellman-Ford)

简介

贝尔曼-福特算法(Bellman-Ford)是由理查德·贝尔曼(Richard Bellman) 和 莱斯特·福特 创立的,求解含负权边的带权有向图的单源最短路径问题的一种算法。它的原理是对图进行 V − 1 V-1 V−1次松弛操作( V V V代表图中的点数),从源点逐次绕过其他顶点,以缩短到达终点的最短路径长度,得到不超过 V − 1 V-1 V−1条边构成的最短路径。其优于迪科斯彻算法(Dijkstra)的方面是边的权值可以为负数、实现简单,缺点是时间复杂度过高,高达 O ( V E ) O(VE) O(VE)( E E E代表边数)。不能处理带负权边的无向图

Bellman-Ford算法的限制条件为:

  • 图中不能包含权值总和为负值的回路(负权值回路

Bell-Ford算法专用处理可能存在负环有限路线单源最短路问题。

算法思想

Bellman-Ford算法构造一个最短路径长度数组序列 d i s t 1 [ u ] , d i s t 2 [ u ] , ⋯ , d i s t n − 1 [ u ] dist^1[u],dist^2[u],\cdots,dist^{n-1}[u] dist1[u],dist2[u],⋯,distn−1[u]。其中:

  • d i s t 1 [ u ] dist^1[u] dist1[u]为从源点 v v v到终点 u u u的只经过一条边的最短路径长度,并有 d i s t 1 [ u ] = e d g e [ v ] [ u ] dist^1[u]=edge[v][u] dist1[u]=edge[v][u]
  • d i s t 2 [ u ] dist^2[u] dist2[u]为从源点 v v v最多经过两条边到达终点 u u u的最短路径长度
  • d i s t 3 [ u ] dist^3[u] dist3[u]为从源点 v v v出发最多经过不构成负权值回路的三条边到达终点 u u u的最短路径长度
  • ⋯ \cdots ⋯
  • d i s t n − 1 [ u ] dist^{n-1}[u] distn−1[u]为从源点 v v v出发最多经过不构成负权值回路的 n − 1 n-1 n−1条边到达终点 u u u的最短路径长度

算法的最终目的是计算出 d i s t n − 1 [ u ] dist^{n-1}[u] distn−1[u],为源点 v v v到顶点 u u u的最短路径长度

算法执行过程

a. 初始化操作,源点 s s s到自己的距离为 0 0 0,源点到其他点的距离为正 ∞ \infty ∞

b. 第一次迭代,找到不超过1条边的最短路

c. 第二次迭代,找到不超过2条边的最短路

d. 第三次迭代,找到不超过3条边的最短路

e. 第四次迭代,找到不超过4条边的最短路

以此类推,可迭代次数是无数次的,但是如果不存在负环,那么当迭代次数与边数相等时就保证了结果

很重要的一点是每次迭代都是在上一次的基础上进行的,因此在代码实现时要注意保留上一次的结果,在上一次的基础上计算。

应用

题目描述

给定一个 n n n个点 m m m条边的有向图,图中可能存在重边和自环,边权可能为负数。

请你求出从 1 1 1号点到 n n n号点的最多经过 k k k条边的最短距离,如果无法从 1 1 1号点走到 n n n号点,输出 i m p o s s i b l e impossible impossible。

注意:图中可能存在负权回路

输入格式

第一行包含三个整数 n , m , k n,m,k n,m,k。

接下来 m m m行,每行包含三个整数 x , y , z x,y,z x,y,z,表示存在一条从点 x x x到点 y y y的有向边,边长为 z z z。

输出格式

输出一个整数,表示从 1 1 1号点到 n n n号点的最多经过 k k k条边的最短距离。

如果不存在满足条件的路径,则输出“impossible”。

数据范围

1 ≤ n , k ≤ 500 1≤n,k≤500 1≤n,k≤500,

1 ≤ m ≤ 10000 1≤m≤10000 1≤m≤10000,

任意边长的绝对值不超过 10000 10000 10000。

输入样例:

3 3 11 2 12 3 11 3 3

输出样例:

3

分析

因为存在可能存在负权边,所以Dijkstra算法无法完成。又因为可能存在负环,SPFA算法也无法完成。按道理来说,只要有负环且不限路径数,答案就可能是负无穷,Bellman-Ford算法也不能完成。但是本题给定了路径数k的限制,所以可以用Bellman-Ford算法来实现。

代码

import java.util.Arrays;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int m = sc.nextInt();int k = sc.nextInt();// 邻接矩阵int[][] g = new int[n][n];final int INF = Integer.MAX_VALUE / 2;// 初始化for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {g[i][j] = (i == j) ? 0 : INF;}}// 存图for (int i = 0; i < m; i++) {int x = sc.nextInt() - 1;int y = sc.nextInt() - 1;int z = sc.nextInt();g[x][y] = z;}// dist[x] = y 代表从「源点/起点」到 x 的最短距离为 yint[] dist = new int[n];// 初始化源点到自己的距离为0,源点到其他点的距离为正无穷Arrays.fill(dist, INF);dist[0] = 0;// 迭代k次for (int limt = 0; limt < k; limt++) {int[] clone = dist.clone();// 更新最短距离for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {dist[j] = Math.min(dist[j], clone[i] + g[i][j]);}}}if (dist[n - 1] >= INF) {System.out.println("impossible");}System.out.println(dist[n - 1]);}
}
  • 时间复杂度为 O ( n m ) O(nm) O(nm)

LeetCode 787. K 站中转内最便宜的航班

题目描述

  • 787. K 站中转内最便宜的航班

Bellman Ford + 邻接矩阵

本题中「限制最多经过不超过 k k k 个点」等价于「限制最多不超过 k + 1 k + 1 k+1 条边」,因此可以使用 Bellman Ford 来求解。

class Solution {public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {final int INF = Integer.MAX_VALUE / 2;int[][] g = new int[n][n];// 邻接矩阵初始化for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {g[i][j] = i == j ? 0 : INF;}}for (int[] f : flights) {g[f[0]][f[1]] = f[2];}// dist[x] = y 代表从「源点/起点」到 x 的最短距离为 yint[] dist = new int[n];// 初始化源点到自己的距离为0,源点到其他点的距离为正无穷Arrays.fill(dist, INF);dist[src] = 0;// 迭代k + 1次for (int limit = 0; limit < k + 1; limit++) {// 复制上一次的迭代结果int[] clone = dist.clone();// 更新最短距离for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {dist[j] = Math.min(dist[j], clone[i] + g[i][j]);}}}return dist[dst] >= INF ? -1 : dist[dst];}
}
  • 时间复杂度: O ( k ∗ n 2 ) O(k * n^2) O(k∗n2)
  • 空间复杂度: O ( n 2 ) O(n^2) O(n2)

Reference

  • 贝尔曼-福特算法

  • Bellman-Ford算法

  • 运用 Bellman Ford 求解有限制的最短路问题

LeetCode 787. K 站中转内最便宜的航班(图/Bellman Ford算法)相关推荐

  1. LeetCode——787. K 站中转内最便宜的航班(Cheapest Flights Within K Stops)[中等]——分析及代码(Java)

    LeetCode--787. K 站中转内最便宜的航班[Cheapest Flights Within K Stops][中等]--分析及代码[Java] 一.题目 二.分析及代码 1. 动态规划 ( ...

  2. LeetCode 787.K站中转内最便宜的航班

    LeetCode 787.K站中转内最便宜的航班 有 n 个城市通过 m 个航班连接.每个航班都从城市 u 开始,以价格 w 抵达 v. 现在给定所有的城市和航班,以及出发城市 src 和目的地 ds ...

  3. LeetCode 787. K 站中转内最便宜的航班(Dijkstra最短路径 + 优先队列)

    文章目录 1. 题目 2. 解题 1. 题目 有 n 个城市通过 m 个航班连接.每个航班都从城市 u 开始,以价格 w 抵达 v. 现在给定所有的城市和航班,以及出发城市 src 和目的地 dst, ...

  4. [leetcode] 787 K 站中转内最便宜的航班

    题目链接 题目大意: 给定一个有向图,从 u → v u\to v u→v有一条长度为 w w w的边 问从 s s s到 t t t的路径中,最多经过 k k k次中转的最短路径是多少? 思路: 首 ...

  5. 787. K 站中转内最便宜的航班(动态规划)

    package com.wsq.leetcode; /*** 787. K 站中转内最便宜的航班* @author wsq* @date 2020/10/21有 n 个城市通过 m 个航班连接.每个航 ...

  6. leetcode每日一题系列——787. K 站中转内最便宜的航班

    787. K 站中转内最便宜的航班 难度中等346收藏分享切换为英文接收动态反馈 有 n 个城市通过一些航班连接.给你一个数组 flights ,其中 flights[i] = [fromi, toi ...

  7. 787. K 站中转内最便宜的航班(加权有向图的最短路径)

    题目:787. K 站中转内最便宜的航班 两种方法: 方法一: 思路: 加权图的最短路径 1. 首先将航线转化为字典形式存储.(当前城市–下一城市–费用) 2. 建一个双向队列,元素为元组形式.(当前 ...

  8. 【力扣】787. K 站中转内最便宜的航班加权——有向图最短路径

    前言 我感觉这题比较有代表性,所以记录一下,这题是加权有向图中求最短路径的问题. 题目 787. K 站中转内最便宜的航班 动态规划 假设有一条路径是[src, i, ..., j, dst],解法一 ...

  9. 力扣787. K 站中转内最便宜的航班

    有 n 个城市通过一些航班连接.给你一个数组 flights ,其中 flights[i] = [fromi, toi, pricei] ,表示该航班都从城市 fromi 开始,以价格 pricei ...

最新文章

  1. 收藏!机器学习算法分类图谱及其优缺点综合分析
  2. leetcode-387-字符串中的第一个唯一字符
  3. 搞定常见垃圾收集器【Java】
  4. TCP三次握手详解及释放连接过程
  5. 如何才能成为优秀的测试工程师?
  6. 转:Linux 2.4.x内核软中断机制
  7. 哈希表及处理冲突的方法
  8. The type XXX is not API (restriction on required library 'D:\jdk-64\jre\lib\rt.jar')
  9. cad中计算机的快捷键,CAD常用快捷键汇总
  10. (附源码)springboot菠萝大学课室预约分析与设计 毕业设计641656
  11. heeds matlab,Ricardo IGNITE下载-整车性能仿真分析软件Ricardo IGNITE下载v2018.1 最新版-西西软件下载...
  12. JVM内存模型和性能调优:JVM整体结构及内存模型- 第10篇
  13. 脉冲宽度调制pdm_如何通俗易懂地解释「脉冲宽度调制(PWM)」?
  14. JAVA数据结构--Arraylist
  15. 会声会影无法导入.ts文件编辑解决办法
  16. Unity FACEGOOD Audio2Face 通过音频驱动面部BlendShape
  17. 在 Node.js 中操作 Redis
  18. uni-app解决百度API h5跨域问题
  19. WMS系统条码作业项目实施经验浅谈
  20. JAVA基础之题目练习

热门文章

  1. 庖丁解牛:USB 驱动开发技术彻底解密
  2. 妻子的容颜,与丈夫有关
  3. 如何实现C++中类编写的头文件和源文件的拆分
  4. Postgresql设置远程访问(需要设置防火墙或者关闭防火墙)
  5. vc2010设置为静态编译
  6. C++中文车牌识别检测系统源码
  7. python 三维绘图_Python三维绘图--Matplotlib
  8. 一般报java.lang.NullPointerException的原因有以下几种
  9. 微信小程序地图获取地点信息(打卡签到功能为例)-2020-7-26
  10. Vben Admin 二(登录页)