There are n
cities connected by m
flights. Each flight starts from city u
and arrives at v
with a price w
.
Now given all the cities and flights, together with starting city src
and the destination dst
, your task is to find the cheapest price from src
to dst
with up to k
stops. If there is no such route, output -1
.
Example 1: Input: n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] src = 0, dst = 2, k = 1 Output: 200 Explanation: The graph looks like this: The cheapest price from city0
to city2
with at most 1 stop costs 200, as marked red in the picture.
Example 2: Input: n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]] src = 0, dst = 2, k = 0 Output: 500 Explanation: The graph looks like this: The cheapest price from city0
to city2
with at most 0 stop costs 500, as marked blue in the picture.
Constraints:
- The number of nodes
n
will be in range[1, 100]
, with nodes labeled from0
ton
- 1
. - The size of
flights
will be in range[0, n * (n - 1) / 2]
. - The format of each flight will be
(src,
dst
, price)
. - The price of each flight will be in the range
[1, 10000]
. k
is in the range of[0, n - 1]
.- There will not be any duplicated flights or self cycles.
Related Topics:
Dynamic Programming, Heap, Breadth-first Search
Similar Questions:
With k
stops, the longest path has k + 1
edges. So, using Bellman-ford algorithm, we should relax k + 1
times.
The relaxation happens from layer to layer. This is to prevent using distance in layer i
when relaxing from layer i-1
to layer i
.
// OJ: https://leetcode.com/problems/cheapest-flights-within-k-stops/
// Author: github.com/lzl124631x
// Time: O(K * (N+ E))
// Space: O(N)
class Solution {
public:
int findCheapestPrice(int n, vector<vector<int>>& A, int src, int dst, int K) {
vector<int> dist(n, 1e8);
dist[src] = 0;
for (int i = 0; i <= K; ++i) {
auto tmp = dist;
for (auto &e : A) {
int u = e[0], v = e[1], w = e[2];
dist[v] = min(dist[v], tmp[u] + w);
}
}
return dist[dst] == 1e8 ? -1 : dist[dst];
}
};
// OJ: https://leetcode.com/problems/cheapest-flights-within-k-stops/
// Author: github.com/lzl124631x
// Time: O(KElogE)
// Space: O(KN + E)
class Solution {
typedef array<int, 3> item; // distance, cityId, # stops left
public:
int findCheapestPrice(int n, vector<vector<int>>& E, int src, int dst, int k) {
vector<vector<pair<int, int>>> G(n);
for (auto &e : E) G[e[0]].emplace_back(e[1], e[2]);
priority_queue<item, vector<item>, greater<>> pq;
++k;
pq.push({0, src, k});
vector<vector<int>> dist(k + 1, vector<int>(n, INT_MAX));
for (int i = 0; i <= k; ++i) dist[i][src] = 0;
while (pq.size()) {
auto [cost, u, stop] = pq.top();
pq.pop();
if (cost > dist[stop][u]) continue;
if (u == dst) return cost;
if (stop == 0) continue;
for (auto &[v, w] : G[u]) {
if (dist[stop - 1][v] > cost + w) {
dist[stop - 1][v] = cost + w;
pq.push({dist[stop - 1][v], v, stop - 1});
}
}
}
return -1;
}
};
A plain BFS also works, but it doesn't prioritize low cost paths first so it might be less efficient.
// OJ: https://leetcode.com/problems/cheapest-flights-within-k-stops/
// Author: github.com/lzl124631x
// Time: O(KE)
// Space: O(N + E)
class Solution {
public:
int findCheapestPrice(int n, vector<vector<int>>& E, int src, int dst, int k) {
vector<vector<pair<int, int>>> G(n);
for (auto &e : E) G[e[0]].emplace_back(e[1], e[2]);
queue<pair<int, int>> q; // cityId, cost
q.emplace(src, 0);
vector<int> dist(n, INT_MAX);
dist[src] = 0;
int step = 0;
while (step <= k) {
int cnt = q.size();
while (cnt--) {
auto [u, cost] = q.front();
q.pop();
for (auto &[v, w] : G[u]) {
if (dist[v] > cost + w) { // Note that we shouldn't use `dist[u]` here. Because `dist[u]` might get updated using two jumps but the `cost` here corresponds to one jump.
dist[v] = cost + w;
q.emplace(v, dist[v]);
}
}
}
++step;
}
return dist[dst] == INT_MAX ? -1 : dist[dst];
}
};