#include using namespace std; #define FOR(I,X,Y) for(long long (I)=(X);(I)<(Y);(I)++) #define REP(I,X,Y) for(long long (I)=(Y)-1;(I)>=(X);(I)--) #define ALL(X) (X).begin(),(X).end() #define pb push_back #define COUNT(V,X) upper_bound((V).begin(),(V).end(),X)-lower_bound((V).begin(),(V).end(),X) #define debug(x) cerr<<#x<<':'<> edges; void add(long long u,long long v){edges.push_back(make_tuple(u,v,1,1));} void add(long long u,long long v,long long weight){edges.push_back(make_tuple(u,v,weight,1));} void add(long long u,long long v,long long weight,long long capacity){edges.push_back(make_tuple(u,v,weight,capacity));} }; //辞書順最小最短経路を返す vector Path(const Graph &G,const long long &start,const long long &goal){ vector>> adj(G.V),adj2(G.V); for(auto t:G.edges)adj[get<0>(t)].push_back(make_pair(get<1>(t),get<2>(t))); for(auto t:G.edges)adj2[get<1>(t)].push_back(make_pair(get<0>(t),get<2>(t))); long long dmin[G.V]; for(long long i = 0;i < G.V;i++)dmin[i] = -1; priority_queue,vector>,greater>> pque; pque.push(make_pair(0,goal)); pair p; while(pque.size()){ p = pque.top();pque.pop(); if(dmin[p.second] == -1){ dmin[p.second] = p.first; for(auto x:adj[p.second])if(dmin[x.first] == -1)pque.push(make_pair(dmin[p.second]+x.second,x.first)); } } long long now = start; vector ans(1,now); while(now != goal){ sort(ALL(adj2[now])); for(long long i = 0;i < adj2[now].size();i++){ pair p = adj2[now][i]; if(dmin[now] == dmin[p.first]+p.second){ ans.push_back(p.first); now = p.first; break; } } } return ans; } signed main(){ Graph G; ll N,M,s,g,a,b,c; cin >> N >> M >> s >> g; G.V = N; G.E = 2*M; FOR(i,0,M){ cin >> a >> b >> c; G.add(a,b,c); G.add(b,a,c); } vector ans = Path(G,s,g); FOR(i,0,ans.size()-1)cout << ans[i] << ' '; cout << ans[ans.size()-1] << endl; }