787. K 站中转内最便宜的航班
有 n 个城市通过 m 个航班连接。
每个航班都从城市 u 开始,以价格 w 抵达 v。
现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,
你的任务是找到从src 到 dst 最多经过 k 站中转的最便宜的价格。
如果没有这样的路线,则输出 -1。
提示:
1) n 范围是 [1, 100],城市标签从 0 到 n - 1
2) 航班数量范围是 [0, n * (n - 1) / 2]
3) 每个航班的格式 (src, dst, price)
4) 每个航班的价格范围是 [1, 10000]
5) k 范围是 [0, n - 1]
6) 航班没有重复,且不存在自环
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cheapest-flights-within-k-stops
这里理解和分析一下题意:
1.这题很明显, 就是求有向图中 **两个点之间(src, dst)** 的 ***最短路径***。
2.不过这里给你加了一个限定了条件,点src和点dst之间的节点不允许超过K个。
3.抛开***只允许中转K次***这个条件, 这个题就是赤裸裸的求最短路径问题。
4.图中求解最短路径的算法有Dijkstra, bellman-ford等,
当然也可以使用最小生成树算法(prim算法等)来求解节点间的最短路径。
3. 这题不就是求解最短路径再加一个限制条件K嘛?
那就在求解最短路径的过程中,
除了记录当前最短路径值外,附加再记录K值呗。
解题思路:
在这里的话,我是使用了最小生成树的prim算法来求解两个节点之间的最短路径。
1.首先声明一个二维数组price = new int[n][k+2]来记录两个节点(src, dst)
经过1, 2, ..., k个中间节点时, 两点之间的最短路径。
2.遍历flights, 构建有向图edges
3.从src节点为起始点,
层次遍历结合prim算法构建该有向图的最小生成树
***这里要注意一点:****
***在层次遍历时, 判断是否将节点加入队列中的条件是很重要的***
4.遍历price[dst], 从0到k+1中找到最小的值,
如果不存在这样的最小值, 则返回负-1,否则,返回该最小值
java代码
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
//声明一个二维数组price记录经过n次到当前点i时需要的最小费用
long[][] price = new long[n][K+2];
//初始化price二维数组的值为Integer.MAX_VALUE;
for(int i=0;i<n;i++){
Arrays.fill(price[i], Integer.MAX_VALUE)<