对于从上到下的每一层的图相当于都是经过了一次免费航班
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define x first
#define y second
typedef pair<int, int> PII;
const int N = 12 * (int) 1e4 + 10, M = 144 * (int) 1e5 + 10;
int n, m, k, s, t;
int head[N], edge_end[M], next_edge[M], w[M], edge_index;
bool vis[N];
int d[N];
void add(int ver1, int ver2, int val) {
edge_end[edge_index] = ver2, next_edge[edge_index] = head[ver1], w[edge_index] = val, head[ver1] = edge_index++;
}
void dijkstra() {
priority_queue<PII, vector<PII>, greater<PII>> queue;
memset(d, 0x3f, sizeof d);
d[s] = 0;
queue.push({
0, s});
while (!queue.empty()) {
auto [dis, u] = queue.top();
queue.pop();
if (vis[u]) continue;
vis[u] = true;
for (int i = head[u]; ~i; i = next_edge[i]) {
int ver = edge_end[i];
if (d[u] + w[i] < d[ver]) {
d[ver] = d[u] + w[i];
queue.push({
d[ver], ver});
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head);
cin >> n >> m >> k >> s >> t;
for (int i = 0; i < m; ++i) {
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
add(v, u, w);
// 一共k + 1层图
for (int j = 1; j <= k; ++j) {
add(j * n + u, j * n + v, w);
add(j * n + v, j * n + u, w);
// 建立上一层到当前层的边
add((j - 1) * n + u, j * n + v, 0);
add((j - 1) * n + v, j * n + u, 0);
}
}
for (int i = 0; i < k; ++i) add(i * n + t, (i + 1) * n + t, 0);
dijkstra();
cout << d[k * n + t] << "\n";
return 0;
}
因为层与层之间也会连边, 因此需要 2 M ∗ k + k × M 2M * k + k \times M 2M∗k+k×M条边
为什么需要将每一层的终点向下一层连边?
为了保证终点之间是免费到达的, 防止上一层无法到达下一层, 也就失去了免费航班的机会


京公网安备 11010502036488号