Files
cpp-courseware/2.Course/2.深入浅出程序设计竞赛(提高篇)/最短路/C++源码/01c_dijkstra_path.cpp
T

64 lines
1.8 KiB
C++

// 教学扩展:非负权有向图中,求 s 到 t 的距离并恢复一条最短路线。
// 输入第一行 n m s t,接着 m 行 u v w。与 P3371 的输入不同。
// 可达:第一行输出距离,第二行输出路线中的顶点编号。
// 不可达:只输出 UNREACHABLE。C++11;时间 O(n*n+m)。
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;
struct Edge {
int to;
ll w;
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, s, t;
if (!(cin >> n >> m >> s >> t)) return 0;
vector<vector<Edge>> g(n + 1);
for (int i = 0; i < m; ++i) {
int u, v;
ll w;
cin >> u >> v >> w;
g[u].push_back({v, w});
}
const ll INF = (1LL << 60);
vector<ll> dis(n + 1, INF);
vector<bool> used(n + 1, false);
vector<int> pre(n + 1, -1);
dis[s] = 0;
for (int round = 0; round < n; ++round) {
int u = -1;
for (int v = 1; v <= n; ++v) {
if (!used[v] && (u == -1 || dis[v] < dis[u])) u = v;
}
if (u == -1 || dis[u] == INF) break;
used[u] = true;
for (const Edge& e : g[u]) {
ll nd = dis[u] + e.w;
if (nd < dis[e.to]) {
dis[e.to] = nd;
pre[e.to] = u; // 与成功改善距离的路线保持一致。
}
}
}
// 没有路线时不能只把终点放进列表,伪装成一条路径。
if (dis[t] == INF) {
cout << "UNREACHABLE\n";
return 0;
}
vector<int> path;
for (int v = t; v != -1; v = pre[v]) path.push_back(v);
reverse(path.begin(), path.end());
cout << dis[t] << '\n';
for (size_t i = 0; i < path.size(); ++i) {
if (i) cout << ' ';
cout << path[i];
}
cout << '\n';
return 0;
}