LintCode 1029. 寻找最便宜的航行旅途(最多经过k个中转站)
题目描述
有n个城市被一些航班所连接。每个航班 (u,v,w) 从城市u出发,到达城市v,价格为w。
给定城市数目 n,所有的航班flights。你的任务是找到从起点src到终点站dst的最便宜线路的价格,而旅途中最多只能中转K次。
如果没有找到合适的线路,返回 -1。
样例
样例 1:
输入:
n = 3,
flights = [[0,1,100],[1,2,100],[0,2,500]],
src = 0, dst = 2, K = 0
输出: 500
样例 2:
输入:
n = 3,
flights = [[0,1,100],[1,2,100],[0,2,500]],
src = 0, dst = 2, K = 1
输出: 200
注意事项
- 总城市数 n 在 1-100 之间,每个城市被标号为 0 到 n-1。
- 航线的总数在 0 到 n * (n - 1) / 2 之间
- 每条航线会被以 [出发站,终点站,价格] 的形式展现。
- 每条航线的价格都在 1-10000之间。
- 中转站的总数限制范围为 0 到 n-1 之间。
- 不会有重复或者自环航线出现
解题思路
单元最短路径问题,加入一个跳步数限制。
Dijkstra或者SPFA可解。
参考代码
SPFA
class Solution {
public:
/**
* @param n: a integer
* @param flights: a 2D array
* @param src: a integer
* @param dst: a integer
* @param K: a integer
* @return: return a integer
*/
int findCheapestPrice(int n, vector<vector<int>> &flights, int src, int dst, int K) {
// write your code here
if (src == dst) return 0;
// SPFA
vector<vector<int>> a;
vector<int> head(n);
queue<pair<int,int>> q;
vector<bool> inq(n);
vector<int> cost(n);
constexpr int INF = 0x3f3f3f3f;
// init
std::fill(head.begin(), head.end(), -1);
for (auto&& f : flights) { // add
a.push_back({f[0], f[1], f[2], head[f[0]]});
head[f[0]] = a.size() - 1;
}
std::fill(inq.begin(), inq.end(), false);
q.push({src, -1});
inq[src] = true;
std::fill(cost.begin(), cost.end(), INF);
cost[src] = 0;
while (!q.empty()) {
auto p = q.front(); q.pop();
int i = p.first;
int step = p.second;
inq[i] = false;
if (step > K) continue;
for (int idx = head[i]; idx >= 0; idx = a[idx][3]) {
int j = a[idx][1];
int tmp = cost[i] + a[idx][2];
if (tmp < cost[j] && step+1 <= K) {
cost[j] = tmp;
if (!inq[j]) {
q.push({j, step + 1});
inq[j] = true;
}
}
}
}
if (cost[dst] == INF) return -1;
return cost[dst];
}
};