#include "bits/stdc++.h" using namespace std; typedef long long ll; typedef unsigned long long ull; typedef vector veci; typedef vector vecll; typedef vector vecs; template using Hash=unordered_map; #define REP(i, a, n) for(ll i = a; i < (ll)(n); i++) #define RREP(i, a, n) for(ll i = n-1; i >= (ll)(a); i--) #define rep(i, n) REP(i, 0, n) #define rrep(i, n) RREP(i, 0, n) #define MD 1000000007 #define _SPLIT " " template T read(){T a;cin >> a;return a;} template void read(T& a){cin >> a;} template void read(T& a, Args&... args){cin >> a; read(args...);} template void rarr(T a, int n){for(int i = 0; i < n; i++) {cin >> a[i];}} template void write(T a){cout << setprecision(12) << a << endl;} template void write(T a, Args... args){cout << setprecision(12) << a << _SPLIT; write(args...);} template void warr(vector a, const char* c = " "){cout << a[0];for(int i = 1; i < (int)a.size(); i++)cout << c << a[i];cout << endl;;} template void warr(T a, int n, const char* c = " "){cout << a[0];for(int i = 1; i < n; i++)cout << c << a[i];cout << endl;} void split(string s, string delim, veci& result){result.clear();string::size_type pos = 0;while(pos != string::npos){string::size_type p = s.find(delim, pos);if(p == string::npos){result.push_back(atoi(s.substr(pos).data()));break;}else {result.push_back(atoi(s.substr(pos, p - pos).data()));}pos = p + delim.size();}} void split(string s, string delim, vecs& result){result.clear();string::size_type pos = 0;while(pos != string::npos){string::size_type p = s.find(delim, pos);if(p == string::npos){result.push_back(s.substr(pos));break;}else {result.push_back(s.substr(pos, p - pos));}pos = p + delim.size();}} ll gcd(ll a, ll b){while(true){ll k = a % b;if(k == 0)return b;a = b;b = k;}} ll comb(ll n, ll m){ll p=1;m=min(m,n-m);for(ll i=1;i<=m;i++){p*=n-i+1;p/=i;}return p;} typedef pair> my_pair; bool operator<(vector& a,vector& b){ int size=min(a.size(),b.size()); for(int i=0;ib[i])return false; } return (int)a.size()==size; } struct WeightedStaticGraph { typedef int Vertex; typedef my_pair Weight; typedef my_pair Dist; static const Dist InfDist; struct To { Vertex to; Weight w; To() { } To(Vertex to_, Weight w_): to(to_), w(w_) { } }; typedef std::pair Edge; typedef const To *const_iterator; void init(int n_, const std::vector &edges) { n = n_; int m = edges.size(); tos.resize(m+1); offsets.resize(n+1); for(int e = 0; e < m; e ++) offsets[edges[e].first] ++; for(int v = 1; v <= n_; v ++) offsets[v] += offsets[v-1]; for(int e = 0; e < m; e ++) tos[-- offsets[edges[e].first]] = edges[e].second; } int numVertices() const { return n; } inline const_iterator edgesBegin(int v) const { return &tos[offsets[v]]; } inline const_iterator edgesEnd(int v) const { return &tos[offsets[v+1]]; } private: int n; std::vector tos; std::vector offsets; }; const WeightedStaticGraph::Dist WeightedStaticGraph::InfDist(0x7fffffffffffffffLL,vector({100})); typedef WeightedStaticGraph Graph; template, typename Index = int> class BinaryHeap { Compare cmp; vector a; vector idx, nodeidx; int pos; public: BinaryHeap(Compare cmp_ = Compare()): cmp(cmp_) { } BinaryHeap(int n, Compare cmp_ = Compare()): cmp(cmp_) { init(n); } void init(int n) { a.resize(n+1); idx.assign(n+1, -1); nodeidx.assign(n+1, -1); pos = 1; } const Value &min() const { return a[1]; } const Value &get(Index i) const { return a[nodeidx[i]]; } Index argmin() const { return idx[1]; } Index size() const { return pos - 1; } bool empty() const { return pos == 1; } const Value &add(Index i, const Value &x) { Index node = nodeidx[i]; if(node >= 0) return a[node]; a[pos] = x; idx[pos] = i; nodeidx[i] = pos; ++ pos; up(pos-1); return x; } const Value &update(Index i, const Value &x) { Index node = nodeidx[i]; if(node < 0) { a[pos] = x; idx[pos] = i; nodeidx[i] = pos; ++ pos; up(pos-1); }else { a[node] = x; up(node); down(node); } return x; } const Value &updatemin(Index i, const Value &x) { Index node = nodeidx[i]; if(node >= 0 && !cmp(x, a[node])) return a[node]; else return update(i, x); } const Value remove(Index i) { if(i < 0) return Value(); Index node = nodeidx[i]; if(node < 0) return Value(); -- pos; idx[node] = idx[pos]; nodeidx[idx[pos]] = node; nodeidx[i] = -1; idx[pos] = -1; swap(a[pos], a[node]); up(node); down(node); return a[pos]; } private: void up(Index i) { for(Index c = i, p = c >> 1; p > 0 && cmp(a[c], a[p]); c >>= 1, p >>= 1) { swap(a[p], a[c]); swap(nodeidx[idx[p]], nodeidx[idx[c]]); swap(idx[p], idx[c]); } } void down(Index i) { Index bottom = pos; for(Index c = i; c * 2 < bottom; ) { Index b = c * 2 + (c * 2 + 1 < bottom && cmp(a[c * 2 + 1], a[c * 2])); if(!cmp(a[b], a[c])) break; swap(a[c], a[b]); swap(nodeidx[idx[c]], nodeidx[idx[b]]); swap(idx[c], idx[b]); c = b; } } }; void dijkstra(const Graph &g, int s, vector &dist) { int n = g.numVertices(); dist.assign(n, Graph::InfDist); vector vis(n); BinaryHeap h(n); h.add(s, my_pair(0,vector({s}))); while(!h.empty()) { int v = h.argmin(); dist[v] = h.get(v); h.remove(v); vis[v] = true; for(Graph::const_iterator it = g.edgesBegin(v), et = g.edgesEnd(v); it != et; ++ it) { if(!vis[it->to]){ vector t=dist[v].second; t.push_back(it->to); h.updatemin(it->to, my_pair(dist[v].first + it->w.first,t)); } } } } int main(void) { int n,m,s,g; vector e; Graph gr; read(n,m,s,g); rep(i,m){ Graph::Edge p; read(p.first,p.second.to,p.second.w.first); e.push_back(p); swap(p.first,p.second.to); e.push_back(p); } gr.init(n,e); vector dist; dijkstra(gr, s, dist); warr(dist[g].second); return 0; }