787. K 站中转内最便宜的航班
有 n 个城市通过 m 个航班连接。每个航班都从城市 u 开始,以价格 w 抵达 v。
现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到从 src 到 dst 最多经过 k 站中转的最便宜的价格。 如果没有这样的路线,则输出 -1。
解题思路:本题的场景可以转化为在给定的最大深度下找加权最短路的问题。那么图的遍历有两种方式,这里对应的给出两种解法。
- 深度优先搜索
class Solution {
public:
void helper(unordered_map<int, vector<vector<int>>>& m, unordered_set<int>& visited, int cur, int K, int dst, int out, int &res) {
if (cur == dst) {res = out; return;}
if (K < 0) return;
for (auto a : m[cur]) {
if (visited.count(a[0]) == 1 || out + a[1] > res) continue;
visited.insert(a[0]);
helper(m, visited, a[0], K - 1, dst, out + a[1], res);
visited.erase(a[0]);
}
}
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
int res = INT_MAX;
unordered_map<int, vector<vector<int>>> m;
unordered_set<int> visited;
for (auto flight : flights) {
m[flight[0]].push_back({flight[1], flight[2]});
}
helper(m, visited, src, K, dst, 0, res);
return res == INT_MAX ? -1 : res;
}
};
- 广度优先遍历
class Solution {
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
int res = INT_MAX;
unordered_map<int, vector<vector<int>>> m;
unordered_set<int> visited;
for (auto flight : flights) {
m[flight[0]].push_back({flight[1], flight[2]});
}
int cnt = 0;
queue<vector<int>> q{{{src, 0}}};
while (!q.empty()) {
for (int i = q.size(); i > 0; --i) {
auto t = q.front(); q.pop();
if (t[0] == dst) {res = min(res, t[1]);}
for (auto a : m[t[0]]) {
if (t[1] + a[1] > res) continue;
q.push({a[0], t[1] + a[1]});
}
}
if (cnt++ > K) break;
}
return res == INT_MAX ? -1 : res;
}
};
参考资料