// 教学扩展:非负权有向图中,求 s 到 t 的距离并恢复一条最短路线。 // 输入第一行 n m s t,接着 m 行 u v w。与 P3371 的输入不同。 // 可达:第一行输出距离,第二行输出路线中的顶点编号。 // 不可达:只输出 UNREACHABLE。C++11;时间 O(n*n+m)。 #include #include #include 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> 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 dis(n + 1, INF); vector used(n + 1, false); vector 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 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; }