-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
187 lines (160 loc) · 5.62 KB
/
main.cpp
File metadata and controls
187 lines (160 loc) · 5.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Source: https://leetcode.com/problems/cheapest-flights-within-k-stops
// Title: Cheapest Flights Within K Stops
// Difficulty: Medium
// Author: Mu Yang <http://muyang.pro>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// There are `n` cities connected by some number of flights. You are given an array `flights` where `flights[i] = [from_i, to_i, price_i]` indicates that there is a flight from city `from_i` to city `to_i` with cost `price_i`.
//
// You are also given three integers `src`, `dst`, and `k`, return **the cheapest price** from `src` to `dst` with at most `k` stops. If there is no such route, return `-1`.
//
// **Example 1:**
// https://assets.leetcode.com/uploads/2022/03/18/cheapest-flights-within-k-stops-3drawio.png
//
// ```
// Input: n = 4, flights = [[0,1,100],[1,2,100],[2,0,100],[1,3,600],[2,3,200]], src = 0, dst = 3, k = 1
// Output: 700
// Explanation:
// The graph is shown above.
// The optimal path with at most 1 stop from city 0 to 3 is marked in red and has cost 100 + 600 = 700.
// Note that the path through cities [0,1,2,3] is cheaper but is invalid because it uses 2 stops.
// ```
//
// **Example 2:**
// https://assets.leetcode.com/uploads/2022/03/18/cheapest-flights-within-k-stops-1drawio.png
//
// ```
// Input: n = 3, flights = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 1
// Output: 200
// Explanation:
// The graph is shown above.
// The optimal path with at most 1 stop from city 0 to 2 is marked in red and has cost 100 + 100 = 200.
// ```
//
// **Example 3:**
// https://assets.leetcode.com/uploads/2022/03/18/cheapest-flights-within-k-stops-2drawio.png
//
// ```
// Input: n = 3, flights = [[0,1,100],[1,2,100],[0,2,500]], src = 0, dst = 2, k = 0
// Output: 500
// Explanation:
// The graph is shown above.
// The optimal path with no stops from city 0 to 2 is marked in red and has cost 500.
// ```
//
// **Constraints:**
//
// - `2 <= n <= 100`
// - `0 <= flights.length <= (n * (n - 1) / 2)`
// - `flights[i].length == 3`
// - `0 <= from_i, to_i < n`
// - `from_i != to_i`
// - `1 <= price_i <= 10^4`
// - There will not be any multiple flights between two cities.
// - `0 <= src, dst, k < n`
// - `src != dst`
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <climits>
#include <functional>
#include <queue>
#include <vector>
using namespace std;
// BFS + Heap (Dijkstra)
class Solution {
using Item = tuple<int, int, int>; // cost, city, step
using Edge = pair<int, int>; // to, price
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
// Init graph
auto graph = vector(n, vector<Edge>());
for (auto& flight : flights) {
int from = flight[0], to = flight[1], price = flight[2];
graph[from].push_back({to, price});
}
// BFS
auto costs = vector(n, vector(k + 2, INT_MAX)); // (city, step) -> cost
auto queue = priority_queue(greater(), std::move(vector<Item>())); // min-heap
queue.push({0, src, 0});
while (!queue.empty()) {
auto [cost, city, step] = queue.top();
queue.pop();
// Found
if (city == dst) return cost;
// Visited
if (cost >= costs[city][step]) continue;
costs[city][step] = cost;
// No more step
if (step == k + 1) continue;
// Next step
auto nextStep = step + 1;
for (auto [next, price] : graph[city]) {
auto nextCost = cost + price;
if (nextCost >= costs[next][nextStep]) continue;
queue.push({nextCost, next, nextStep});
}
}
return -1;
}
};
// BFS + Queue
class Solution2 {
using Edge = pair<int, int>; // to, price
using Item = tuple<int, int>; // cost, city
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
// Init graph
auto graph = vector(n, vector<Edge>());
for (auto& flight : flights) {
int from = flight[0], to = flight[1], price = flight[2];
graph[from].push_back({to, price});
}
// BFS
auto costs = vector(n, INT_MAX); // city -> cost
auto currQueue = queue<Item>();
auto nextQueue = queue<Item>();
currQueue.push({0, src});
for (int step = 0; step <= k + 1; ++step) {
while (!currQueue.empty()) {
auto [cost, city] = currQueue.front();
currQueue.pop();
// Visited
if (cost >= costs[city]) continue;
costs[city] = cost;
// No more steps
if (step == k + 1) continue;
// Next step
for (auto [next, price] : graph[city]) {
auto nextCost = cost + price;
if (nextCost >= costs[next]) continue;
nextQueue.push({nextCost, next});
}
}
swap(currQueue, nextQueue);
}
return costs[dst] != INT_MAX ? costs[dst] : -1;
}
};
// Bellman-Ford
class Solution3 {
constexpr static int kInf = INT_MAX / 2;
public:
int findCheapestPrice(int n, const vector<vector<int>>& flights, int src, int dst, int k) {
auto currCosts = vector(n, kInf);
currCosts[src] = 0;
for (int step = 0; step <= k; ++step) {
auto nextCosts = currCosts; // copy, avoid racing
bool updated = false;
for (const auto& flight : flights) {
int from = flight[0], to = flight[1], price = flight[2];
int nextCost = currCosts[from] + price;
if (nextCosts[to] > nextCost) {
nextCosts[to] = nextCost;
updated = true;
}
}
if (!updated) break;
swap(currCosts, nextCosts);
}
return currCosts[dst] >= kInf ? -1 : currCosts[dst];
}
};