classSolution { public: using tiii = tuple<int, int, int>; intfindCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K){ ++K; vector<vector<pair<int, int>>> g(n); for (constauto &f : flights) { g[f[0]].emplace_back(f[1], f[2]); } priority_queue<tiii, vector<tiii>, greater<tiii>> q; q.emplace(0, src, 0); while (!q.empty()) { auto [cost, u, k] = q.top(); q.pop(); if (u == dst) return cost; if (k == K) continue; for (auto [v, c] : g[u]) { q.emplace(cost + c, v, k + 1); } } return-1; } };
bellman-ford变种 O(K*E) time O(VK) space 因为最多只能K个stop,所以relax K次就可以了 每次松弛操作实际上是对相邻节点的访问,第n次松弛操作保证了所有深度为n的路径最短。由于图的最短路径最长不会经过超过 |V|-1 条边,所以可知贝尔曼-福特算法所得为最短路径。 K个stop转换成K+1次飞行,直飞就是1次飞行 f[i][j]表示最多i次飞行从src到达j的最小开销 这里所有的f[i][src] = 0 where 0 <= i <= K + 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution { public: intfindCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K){ vector<vector<int>> d(K + 2, vector<int>(n, 1e7)); d[0][src] = 0; // 0次飞行哪也去不了,肯定为0 for (int i = 1; i <= K + 1; ++i) { d[i][src] = 0; // 任何次数的飞行都是回到原点 for (constauto &f : flights) { d[i][f[1]] = min(d[i][f[1]], d[i - 1][f[0]] + f[2]); // 进行relax } } return d[K + 1][dst] == 1e7 ? -1 : d[K + 1][dst]; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution { public: intfindCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K){ ++K; vector<vector<int>> d(K + 1, vector<int>(n, 1e7)); d[0][src] = 0; for (int i = 1; i <= K; ++i) { d[i][src] = 0; for (constauto &f : flights) { d[i][f[1]] = min(d[i][f[1]], d[i - 1][f[0]] + f[2]); } } return d[K][dst] == 1e7 ? -1 : d[K][dst]; } };
滚动数组空间优化以后的bellman-ford变种 O(K*E) time O(V) space
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution { public: intfindCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K){ ++K; vector<vector<int>> d(2, vector<int>(n, 1e7)); d[0][src] = 0; for (int i = 1; i <= K; ++i) { d[i & 1][src] = 0; for (constauto &f : flights) { d[i & 1][f[1]] = min(d[i & 1][f[1]], d[(i - 1) & 1][f[0]] + f[2]); } } return d[K & 1][dst] == 1e7 ? -1 : d[K & 1][dst]; } };
classSolution { public: intfindCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K){ ++K; vector<vector<pair<int, int>>> g(n); for (constauto &f : flights) { g[f[0]].emplace_back(f[1], f[2]); } queue<pair<int, int>> q{{{src, 0}}}; int k = 0, res = INT_MAX; while (!q.empty() && k <= K) { for (int i = q.size(); i > 0; --i) { auto [u, cost] = q.front(); q.pop(); if (u == dst) { res = min(res, cost); } for (auto [v, c] : g[u]) { if (cost + c < res) { q.emplace(v, cost + c); } } } ++k; } return res == INT_MAX ? -1 : res; } };