module main; // https://yukicoder.me/submissions/13999 より import std; struct Edge { int to; long cost; } int N, M, S, G; // ダイクストラ法で使う(P[0]は頂点の番号、P[1]は最短距離) alias P = Tuple!(int, long); immutable INF = 10L ^^ 18; Edge[][] Graph; long[] dist; /* ダイクストラ法 入力:開始点 s 計算量:O(|E|log|V|) */ void dijkstra(int s) { dist = new long[](N); dist[] = INF; dist[s] = 0; auto que = heapify!"a[1] > b[1]"([P(s, 0L)]); while (!que.empty()) { P p = que.front; que.popFront; int v = p[0]; if (dist[v] < p[1]) continue; foreach (e; Graph[v]) { if (dist[e.to] <= dist[v] + e.cost) continue; dist[e.to] = dist[v] + e.cost; que.insert(P(e.to, dist[e.to])); } } } void main() { // 入力 readln.chomp.formattedRead("%d %d %d %d", N, M, S, G); Graph.length = N; foreach (_; 0 .. M) { int a, b; long c; readln.chomp.formattedRead("%d %d %d", a, b, c); Graph[a] ~= Edge(b, c); Graph[b] ~= Edge(a, c); } // 答えの計算 dijkstra(G); // 無向グラフなのでゴールからたどっても良い //辞書順最小になるように、経路復元しながら貪欲的に選ぶ auto ans = [S]; int now = S; while (true) { int next = 1 << 29; foreach (e; Graph[now]) { if (dist[now] == dist[e.to] + e.cost) next = min(next, e.to); } now = next; ans ~= now; if (now == G) break; } // 答えの出力 writefln("%(%d %)", ans); }