LeetCode 787. K 站中转内最便宜的航班(图/Bellman Ford算法)
文章目录
- 贝尔曼-福特算法(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算法)相关推荐
- LeetCode——787. K 站中转内最便宜的航班(Cheapest Flights Within K Stops)[中等]——分析及代码(Java)
LeetCode--787. K 站中转内最便宜的航班[Cheapest Flights Within K Stops][中等]--分析及代码[Java] 一.题目 二.分析及代码 1. 动态规划 ( ...
- LeetCode 787.K站中转内最便宜的航班
LeetCode 787.K站中转内最便宜的航班 有 n 个城市通过 m 个航班连接.每个航班都从城市 u 开始,以价格 w 抵达 v. 现在给定所有的城市和航班,以及出发城市 src 和目的地 ds ...
- LeetCode 787. K 站中转内最便宜的航班(Dijkstra最短路径 + 优先队列)
文章目录 1. 题目 2. 解题 1. 题目 有 n 个城市通过 m 个航班连接.每个航班都从城市 u 开始,以价格 w 抵达 v. 现在给定所有的城市和航班,以及出发城市 src 和目的地 dst, ...
- [leetcode] 787 K 站中转内最便宜的航班
题目链接 题目大意: 给定一个有向图,从 u → v u\to v u→v有一条长度为 w w w的边 问从 s s s到 t t t的路径中,最多经过 k k k次中转的最短路径是多少? 思路: 首 ...
- 787. K 站中转内最便宜的航班(动态规划)
package com.wsq.leetcode; /*** 787. K 站中转内最便宜的航班* @author wsq* @date 2020/10/21有 n 个城市通过 m 个航班连接.每个航 ...
- leetcode每日一题系列——787. K 站中转内最便宜的航班
787. K 站中转内最便宜的航班 难度中等346收藏分享切换为英文接收动态反馈 有 n 个城市通过一些航班连接.给你一个数组 flights ,其中 flights[i] = [fromi, toi ...
- 787. K 站中转内最便宜的航班(加权有向图的最短路径)
题目:787. K 站中转内最便宜的航班 两种方法: 方法一: 思路: 加权图的最短路径 1. 首先将航线转化为字典形式存储.(当前城市–下一城市–费用) 2. 建一个双向队列,元素为元组形式.(当前 ...
- 【力扣】787. K 站中转内最便宜的航班加权——有向图最短路径
前言 我感觉这题比较有代表性,所以记录一下,这题是加权有向图中求最短路径的问题. 题目 787. K 站中转内最便宜的航班 动态规划 假设有一条路径是[src, i, ..., j, dst],解法一 ...
- 力扣787. K 站中转内最便宜的航班
有 n 个城市通过一些航班连接.给你一个数组 flights ,其中 flights[i] = [fromi, toi, pricei] ,表示该航班都从城市 fromi 开始,以价格 pricei ...
最新文章
- 收藏!机器学习算法分类图谱及其优缺点综合分析
- leetcode-387-字符串中的第一个唯一字符
- 搞定常见垃圾收集器【Java】
- TCP三次握手详解及释放连接过程
- 如何才能成为优秀的测试工程师?
- 转:Linux 2.4.x内核软中断机制
- 哈希表及处理冲突的方法
- The type XXX is not API (restriction on required library 'D:\jdk-64\jre\lib\rt.jar')
- cad中计算机的快捷键,CAD常用快捷键汇总
- (附源码)springboot菠萝大学课室预约分析与设计 毕业设计641656
- heeds matlab,Ricardo IGNITE下载-整车性能仿真分析软件Ricardo IGNITE下载v2018.1 最新版-西西软件下载...
- JVM内存模型和性能调优:JVM整体结构及内存模型- 第10篇
- 脉冲宽度调制pdm_如何通俗易懂地解释「脉冲宽度调制(PWM)」?
- JAVA数据结构--Arraylist
- 会声会影无法导入.ts文件编辑解决办法
- Unity FACEGOOD Audio2Face 通过音频驱动面部BlendShape
- 在 Node.js 中操作 Redis
- uni-app解决百度API h5跨域问题
- WMS系统条码作业项目实施经验浅谈
- JAVA基础之题目练习
热门文章
- 庖丁解牛:USB 驱动开发技术彻底解密
- 妻子的容颜,与丈夫有关
- 如何实现C++中类编写的头文件和源文件的拆分
- Postgresql设置远程访问(需要设置防火墙或者关闭防火墙)
- vc2010设置为静态编译
- C++中文车牌识别检测系统源码
- python 三维绘图_Python三维绘图--Matplotlib
- 一般报java.lang.NullPointerException的原因有以下几种
- 微信小程序地图获取地点信息(打卡签到功能为例)-2020-7-26
- Vben Admin 二(登录页)