Problem:
Revenge of the Broken Door
The JAG Kingdom consists of $N$ cities and $M$ bidirectional roads. The $i$-th road ($u_i, v_i, c_i$) connects the city $u_i$ and the city $v_i$ with the length $c_i$. One day, you, a citizen of the JAG Kingdom, decided to go to the city $T$ from the city $S$. However, you know that one of the roads in the JAG Kingdom is currently under construction and you cannot pass the road. You don't know which road it is. You can know whether a road is under construction only when you are in either city connected by the road.
Your task is to minimize the total length of the route in the worst case. You don't need to decide a route in advance of departure and you can choose where to go next at any time. If you cannot reach the city $T$ in the worst case, output '-1'.
Input
The input consists of a single test case formatted as follows.
$N$ $M$ $S$ $T$
$u_1$ $v_1$ $c_1$
:
$u_M$ $v_M$ $c_M$
The first line contains four integers $N, M, S,$ and $T$, where $N$ is the number of the cities ($2 \leq N \leq 100,000$), $M$ is the number of the bidirectional roads ($1 \leq M \leq 200,000$), $S$ is the city you start from ($1 \leq S \leq N$), and $T$ is the city you want to reach to ($1 \leq T \leq N, S \ne T$). The following $M$ lines represent road information: the $i$-th line of the $M$ lines consists of three integers $u_i, v_i, c_i,$ which means the $i$-th road connects the cities $u_i$ and $v_i$ ($1 \leq u_i, v_i \leq N, u_i \ne v_i$) with the length $c_i$ ($1 \leq c_i \leq 10^9$). You can assume that all the pairs of the cities are connected if no road is under construction. That is, there is at least one route from city $x$ to city $y$ with given roads, for all cities $x$ and $y$. It is also guaranteed that there are no multiple-edges, i.e., $\{u_i,v_i\} \ne \{u_j,v_j\}$ for all $1 \leq i < j \leq M$.
Output
Output the minimum total length of the route in the worst case. If you cannot reach the city $T$ in the worst case, output '-1'.
Sample Input 1
3 3 1 3
1 2 1
2 3 5
1 3 3
Output for Sample Input 1
6
Sample Input 2
4 4 1 4
1 2 1
2 4 1
1 3 1
3 4 1
Output for Sample Input 2
4
Sample Input 3
5 4 4 1
1 2 3
2 3 4
3 4 5
4 5 6
Output for Sample Input 3
-1

Submitted solutions:

code_snippet: // #pragma GCC target("avx2")
#pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
// #include<sys/time.h>
// #include<atcoder/modint>

using namespace std;

const int M = 998244353;
const long long LM = 1LL << 60;

using p_que = priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>>;

pair<p_que, long long> dfs(int p, int depth, const vector<vector<int>>& children, const vector<long long>& dist, const vector<vector<pair<long long, int>>>& shortcuts, vector<long long>& res) {
    pair<p_que, long long> p1(p_que(shortcuts[p].begin(), shortcuts[p].end()), 0LL);
    for (auto&& e : children[p]) {
        auto w = dist[e] - dist[p];
        auto p2 = dfs(e, depth + 1, children, dist, shortcuts, res);
        p2.second += w;
        if (p1.first.size() < p2.first.size()) {
            swap(p1, p2);
        }
        while (!p2.first.empty()) {
            auto x = p2.first.top();
            p2.first.pop();
            x.first += p2.second - p1.second;
            p1.first.push(x);
        }
    }
    while (!p1.first.empty()) {
        auto x = p1.first.top();
        if (x.second >= depth) {
            p1.first.pop();
        }
        else {
            res[p] = x.first + p1.second;
            break;
        }
    }
    return p1;
}


int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);
    const int L = 18;
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    --s;
    --t;
    vector<pair<long long, pair<int, int>>> edges(m);
    vector<vector<int>> edge(n);
    for (int i = 0; i < m; ++i) {
        int u, v;
        long long w;
        cin >> u >> v >> w;
        --u;
        --v;
        edges[i] = { w, { u, v } };
        edge[u].push_back(i);
        edge[v].push_back(i);
    }
    vector<int> depth(n, M);
    vector<long long> dist(n, LM);
    vector<vector<int>> parents(L, vector<int>(n, -1));
    vector<vector<int>> children(n);
    vector<bool> in_tree(m);
    {
        priority_queue<pair<long long, pair<int, int>>, vector<pair<long long, pair<int, int>>>, greater<pair<long long, pair<int, int>>>> pq;
        dist[t] = 0;
        depth[t] = 0;
        pq.push({ dist[t], { t, -1 } });
        while (!pq.empty()) {
            auto p = pq.top();
            pq.pop();
            int v = p.second.first;
            int ei = p.second.second;
            if (p.first != dist[v]) {
                continue;
            }
            assert(parents[0][v] == -1);
            if (ei != -1) {
                in_tree[ei] = true;
                int par = v ^ edges[ei].second.first ^ edges[ei].second.second;
                parents[0][v] = par;
                children[par].push_back(v);
            }
            for (auto&& ei : edge[v]) {
                int u = v ^ edges[ei].second.first ^ edges[ei].second.second;
                if (dist[u] > dist[v] + edges[ei].first) {
                    dist[u] = dist[v] + edges[ei].first;
                    depth[u] = depth[v] + 1;
                    pq.push({ dist[u], { u, ei } });
                }
            }
        }
    }
    for (int j = 0; j + 1 < L; ++j) {
        for (int i = 0; i < n; ++i) {
            parents[j + 1][i] = parents[j][i] == -1 ? -1 : parents[j][parents[j][i]];
        }
    }
    auto climb = [&](int u, int d) {
        for (int i = 0; i < L; ++i) {
            if ((d >> i) & 1) {
                u = parents[i][u];
            }
        }
        return u;
    };

    auto lca = [&](int u, int v) {
        if (depth[u] > depth[v]) {
            u = climb(u, depth[u] - depth[v]);
        }
        if (depth[u] < depth[v]) {
            v = climb(v, depth[v] - depth[u]);
        }
        if (u == v) {
            return u;
        }
        for (int i = L - 1; i >= 0; --i) {
            if (parents[i][u] != parents[i][v]) {
                u = parents[i][u];
                v = parents[i][v];
            }
        }
        return parents[0][u];
    };

    vector<vector<pair<long long, int>>> shortcuts(n);
    for (int i = 0; i < m; ++i) {
        if (depth[edges[i].second.first] == M || in_tree[i]) {
            continue;
        }
        int lim = depth[lca(edges[i].second.first, edges[i].second.second)];
        shortcuts[edges[i].second.first].emplace_back(dist[edges[i].second.second] + edges[i].first, lim);
        shortcuts[edges[i].second.second].emplace_back(dist[edges[i].second.first] + edges[i].first, lim);
    }
    vector<long long> bypass(n, LM);

    dfs(t, 0, children, dist, shortcuts, bypass);

    vector<long long> dist2(n, LM);
    {
        p_que pq;
        dist2[t] = 0;
        pq.emplace(dist2[t], t);
        while (!pq.empty()) {
            auto p = pq.top();
            pq.pop();
            int v = p.second;
            if (p.first != dist2[v]) {
                continue;
            }
            for (auto&& ei : edge[v]) {
                int u = v ^ edges[ei].second.first ^ edges[ei].second.second;
                auto nx = max(bypass[u], dist2[v] + edges[ei].first);
                if (dist2[u] > nx) {
                    dist2[u] = nx;
                    pq.emplace(dist2[u], u);
                }
            }
        }
    }
    if (dist2[s] == LM) {
        cout << -1 << '\n';
    }
    else {
        cout << dist2[s] << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 41376
final_rank: 1

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#else
#define NDEBUG
#endif
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i,n) for(ll i=0; i<ll(n); i++)
template <class T> using V = vector<T>;
template <class A, class B> void chmax(A& l, const B& r){ if(l < r) l = r; }
template <class A, class B> void chmin(A& l, const B& r){ if(r < l) l = r; }

template<class T> using nega_queue = priority_queue<T, V<T>, greater<T>>;

#include <utility>
#include <cassert>

namespace nachia{

template<class Elem>
class CsrArray{
public:
    struct ListRange{
        using iterator = typename std::vector<Elem>::iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        Elem& operator[](int i) const { return begi[i]; }
    };
    struct ConstListRange{
        using iterator = typename std::vector<Elem>::const_iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        const Elem& operator[](int i) const { return begi[i]; }
    };
private:
    int m_n;
    std::vector<Elem> m_list;
    std::vector<int> m_pos;
public:
    CsrArray() : m_n(0), m_list(), m_pos() {}
    static CsrArray Construct(int n, std::vector<std::pair<int, Elem>> items){
        CsrArray res;
        res.m_n = n;
        std::vector<int> buf(n+1, 0);
        for(auto& [u,v] : items){ ++buf[u]; }
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        res.m_list.resize(buf[n]);
        for(int i=(int)items.size()-1; i>=0; i--){
            res.m_list[--buf[items[i].first]] = std::move(items[i].second);
        }
        res.m_pos = std::move(buf);
        return res;
    }
    static CsrArray FromRaw(std::vector<Elem> list, std::vector<int> pos){
        CsrArray res;
        res.m_n = pos.size() - 1;
        res.m_list = std::move(list);
        res.m_pos = std::move(pos);
        return res;
    }
    ListRange operator[](int u) { return ListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    ConstListRange operator[](int u) const { return ConstListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    int size() const { return m_n; }
    int fullSize() const { return (int)m_list.size(); }
};

} // namespace nachia

namespace nachia{


struct Graph {
public:
    struct Edge{
        int from, to;
        void reverse(){ std::swap(from, to); }
        int xorval() const { return from ^ to; }
    };
    Graph() : m_n(0), m_e(0), m_isUndir(false) {}
    explicit Graph(int n, bool undirected = false, int m = 0) : m_n(n), m_e(m), m_isUndir(undirected) {}
    explicit Graph(int n, const std::vector<std::pair<int, int>>& edges, int undirected = false) : m_n(n), m_isUndir(undirected){
        m_e.resize(edges.size());
        for(std::size_t i=0; i<edges.size(); i++) m_e[i] = { edges[i].first, edges[i].second };
    }
    template<class Cin>
    static Graph Input(Cin& cin, int n, bool undirected, int m, int offset = 0){
        Graph res(n, undirected, m);
        for(int i=0; i<m; i++){
            int u, v; cin >> u >> v;
            res[i].from = u - offset;
            res[i].to = v - offset;
        }
        return res;
    }
    int numVertices() const noexcept { return m_n; }
    int numEdges() const noexcept { return int(m_e.size()); }
    int addNode() noexcept { return m_n++; }
    int addEdge(int from, int to){ m_e.push_back({ from, to }); return numEdges() - 1; }
    Edge& operator[](int ei) noexcept { return m_e[ei]; }
    const Edge& operator[](int ei) const noexcept { return m_e[ei]; }
    Edge& at(int ei) { return m_e.at(ei); }
    const Edge& at(int ei) const { return m_e.at(ei); }
    auto begin(){ return m_e.begin(); }
    auto end(){ return m_e.end(); }
    auto begin() const { return m_e.begin(); }
    auto end() const { return m_e.end(); }
    bool isUndirected() const noexcept { return m_isUndir; }
    void reverseEdges() noexcept { for(auto& e : m_e) e.reverse(); }
    void contract(int newV, const std::vector<int>& mapping){
        assert(numVertices() == int(mapping.size()));
        for(int i=0; i<numVertices(); i++) assert(0 <= mapping[i] && mapping[i] < newV);
        for(auto& e : m_e){ e.from = mapping[e.from]; e.to = mapping[e.to]; }
        m_n = newV;
    }
    std::vector<Graph> induce(int num, const std::vector<int>& mapping) const {
        int n = numVertices();
        assert(n == int(mapping.size()));
        for(int i=0; i<n; i++) assert(-1 <= mapping[i] && mapping[i] < num);
        std::vector<int> indexV(n), newV(num);
        for(int i=0; i<n; i++) if(mapping[i] >= 0) indexV[i] = newV[mapping[i]]++;
        std::vector<Graph> res; res.reserve(num);
        for(int i=0; i<num; i++) res.emplace_back(newV[i], isUndirected());
        for(auto e : m_e) if(mapping[e.from] == mapping[e.to] && mapping[e.to] >= 0) res[mapping[e.to]].addEdge(indexV[e.from], indexV[e.to]);
        return res;
    }
    CsrArray<int> getEdgeIndexArray(bool undirected) const {
        std::vector<std::pair<int, int>> src;
        src.reserve(numEdges() * (undirected ? 2 : 1));
        for(int i=0; i<numEdges(); i++){
            auto e = operator[](i);
            src.emplace_back(e.from, i);
            if(undirected) src.emplace_back(e.to, i);
        }
        return CsrArray<int>::Construct(numVertices(), src);
    }
    CsrArray<int> getEdgeIndexArray() const { return getEdgeIndexArray(isUndirected()); }
    CsrArray<int> getAdjacencyArray(bool undirected) const {
        std::vector<std::pair<int, int>> src;
        src.reserve(numEdges() * (undirected ? 2 : 1));
        for(auto e : m_e){
            src.emplace_back(e.from, e.to);
            if(undirected) src.emplace_back(e.to, e.from);
        }
        return CsrArray<int>::Construct(numVertices(), src);
    }
    CsrArray<int> getAdjacencyArray() const { return getAdjacencyArray(isUndirected()); }
private:
    int m_n;
    std::vector<Edge> m_e;
    bool m_isUndir;
};

} // namespace nachia

namespace nachia{

struct HeavyLightDecomposition{
private:

    int N;
    std::vector<int> P;
    std::vector<int> PP;
    std::vector<int> PD;
    std::vector<int> D;
    std::vector<int> I;

    std::vector<int> rangeL;
    std::vector<int> rangeR;

public:
    
    HeavyLightDecomposition(const Graph& tree, int root = 0) {
        N = tree.numVertices();
        D.assign(N, 0); D[root] = 2;
        P.assign(N, 0);
        for(auto [u,v] : tree){ D[u] += 1; D[v] += 1; P[u] ^= v; P[v] ^= u; }

        std::vector<int> sz(N, 1);
        std::vector<int> top(N);
        std::vector<int> nx(N, -1);
        int ipos = 0;
        for(int v=0; v<N; v++) if(D[v] == 1) top[N-1-ipos++] = v;

        for(int i=0; i<ipos; i++){
            int v = top[N-1-i];
            if(--D[P[v]] == 1) top[N-1-ipos++] = P[v];
            P[P[v]] ^= v; sz[P[v]] += sz[v];
            if(nx[P[v]] == -1 || sz[nx[P[v]]] < sz[v]) nx[P[v]] = v;
        }
        assert(ipos == N-1 && "HLD input tree traverse failed");
        top[0] = root;
        P[root] = -1;

        PP.resize(N); for(int i=0; i<N; i++) PP[i] = i;
        for(int v : top) if(nx[v] != -1) PP[nx[v]] = PP[v];

        D.assign(N, 0);
        for(int v : top) if(v != root) D[v] = D[P[v]]+1;

        PD.assign(N,N); PD[root] = 0;
        for(int v : top) if(v != root) PD[v] = std::min(PD[PP[v]], PD[P[v]]+1);
        
        rangeL.assign(N,0);
        sz[root] = 1;
        for(int v : top){
            if(v != root && PP[v] == v){
                int p = P[v];
                rangeL[v] = sz[p];
                sz[p] += sz[v];
                sz[v] = rangeL[v] + 1;
            }
            int w = nx[v];
            if(w >= 0){
                rangeL[w] = sz[v];
                sz[v] += sz[w];
                sz[w] = rangeL[w] + 1;
            }
        }
        rangeR = std::move(sz);

        for(int i=0; i<N; i++) top[rangeL[i]] = i;
        I = std::move(top);
    }

    int numVertices() const { return N; }
    int depth(int p) const { return D[p]; }
    int toSeq(int vtx) const { return rangeL[vtx]; }
    int toVtx(int seqidx) const { return I[seqidx]; }
    int toSeq2In(int vtx) const { return rangeL[vtx] * 2 - D[vtx]; }
    int toSeq2Out(int vtx) const { return rangeR[vtx] * 2 - D[vtx] - 1; }
    int parentOf(int v) const { return P[v]; }
    int heavyRootOf(int v) const { return PP[v]; }
    int heavyChildOf(int v) const {
        if(toSeq(v) == N-1) return -1;
        int cand = toVtx(toSeq(v) + 1);
        if(PP[v] == PP[cand]) return cand;
        return -1;
    }

    int lca(int u, int v) const {
        if(PD[u] < PD[v]) std::swap(u, v);
        while(PD[u] > PD[v]) u = P[PP[u]];
        while(PP[u] != PP[v]){ u = P[PP[u]]; v = P[PP[v]]; }
        return (D[u] > D[v]) ? v : u;
        /*
        if(rangeL[u] > rangeL[v]) std::swap(u, v);
        int h = rangeL[u];
        while(h < rangeL[PP[v]]){ v = P[PP[v]]; }
        return rangeL[v] <= h ? v : u;
        */
    }

    int dist(int u, int v) const {
        return depth(u) + depth(v) - depth(lca(u,v)) * 2;
    }

    struct Range{
        int l; int r;
        int size() const { return r-l; }
        bool includes(int x) const { return l <= x && x < r; }
    };

    std::vector<Range> path(int r, int c, bool include_root = true, bool reverse_path = false) const {
        if(PD[c] < PD[r]) return {};
        std::vector<Range> res(PD[c]-PD[r]+1);
        for(int i=0; i<(int)res.size()-1; i++){
            res[i] = { rangeL[PP[c]], rangeL[c]+1 };
            c = P[PP[c]];
        }
        if(PP[r] != PP[c] || D[r] > D[c]) return {};
        res.back() = { rangeL[r]+(include_root?0:1), rangeL[c]+1 };
        if(res.back().l == res.back().r) res.pop_back();
        if(!reverse_path) std::reverse(res.begin(),res.end());
        else for(auto& a : res) a = { N - a.r, N - a.l };
        return res;
    }

    Range subtree(int p) const { return { rangeL[p], rangeR[p] }; }

    int median(int x, int y, int z) const {
        return lca(x,y) ^ lca(y,z) ^ lca(x,z);
    }

    int la(int from, int to, int d) const {
        if(d < 0) return -1;
        int g = lca(from,to);
        int dist0 = D[from] - D[g] * 2 + D[to];
        if(dist0 < d) return -1;
        int p = from;
        if(D[from] - D[g] < d){ p = to; d = dist0 - d; }
        while(D[p] - D[PP[p]] < d){
            d -= D[p] - D[PP[p]] + 1;
            p = P[PP[p]];
        }
        return I[rangeL[p] - d];
    }

    struct ChildrenIterRange {
    struct Iter {
        const HeavyLightDecomposition& hld; int s;
        int operator*() const { return hld.toVtx(s); }
        Iter& operator++(){
            s += hld.subtree(hld.I[s]).size();
            return *this;
        }
        Iter operator++(int) const { auto a = *this; return ++a; }
        bool operator==(Iter& r) const { return s == r.s; }
        bool operator!=(Iter& r) const { return s != r.s; }
    };
        const HeavyLightDecomposition& hld; int v;
        Iter begin() const { return { hld, hld.rangeL[v] + 1 }; }
        Iter end() const { return { hld, hld.rangeR[v] }; }
    };
    ChildrenIterRange children(int v) const {
        return ChildrenIterRange{ *this, v };
    }
};

} // namespace nachia

ll msb(ll x){
  return 63 - __builtin_clzll(x);
}

void testcase(){
  ll N, M, S, T; cin >> N >> M >> S >> T; S--; T--;
  V<V<pair<ll,ll>>> adj(N);
  struct Edge { ll u,v,d; };
  V<Edge> edges(M);
  REP(i,M){
    ll u,v,d; cin >> u >> v >> d; u--; v--;
    adj[u].push_back({v,d});
    adj[v].push_back({u,d});
    edges[i] = {u,v,d};
  }

  V<ll> dist(N,INF), par(N,-1);
  {
    nega_queue<pair<ll,ll>> que;
    auto see = [&](ll v, ll p, ll d) -> void {
      if(d >= dist[v]) return;
      que.push({ d, v });
      dist[v] = d;
      par[v] = p;
    };
    see(T, -1, 0);
    while(que.size()){
      auto [d,v] = que.top(); que.pop();
      if(dist[v] != d) continue;
      for(auto [w,e] : adj[v]) see(w, v, d+e);
    }
  }

  nachia::Graph tree(N);
  REP(i,N) if(i != T) tree.addEdge(i,par[i]);
  auto hld = nachia::HeavyLightDecomposition(tree, T);

  V<V<ll>> st(20, V<ll>(N,INF));
  for(auto [u,v,d] : edges){
    if(dist[u] < dist[v]) swap(u,v);
    if(par[u] == v || par[v] == u) continue;
    ll g = hld.lca(u, v);
    REP(tt,2){
      ll off = dist[v] + d + dist[u];
      for(auto [l,r] : hld.path(g, u, 0)) if(l < r){
        ll b = msb(r - l);
        chmin(st[b][l], off);
        chmin(st[b][r - (1ll << b)], off);
      } swap(u,v);
    }
  }
  
  for(ll b=st.size()-1; b>=0; b--) for(ll i=0; i+(1ll<<b)<N; i++){
    chmin(st[b][i], st[b+1][i]);
    chmin(st[b][i+(1ll<<b)], st[b+1][i]);
  }

  V<ll> altdist(N);
  REP(i,N) if(i){
    ll v = hld.toVtx(i);
    altdist[v] = st[0][i] - dist[v];
  }
  for(auto& x : altdist) if(x > INF / 2) x = INF;

  //for(auto d : dist) cout << d << " ";
  //cout << endl;
  //for(auto d : par) cout << d << " ";
  //cout << endl;
  //for(auto d : altdist) cout << d << " ";
  //cout << endl;
  
  ll ok = INF, ng = -1;
  {
    V<V<pair<ll,pair<ll,ll>>>> fixadj(N);
    for(auto [u,v,d] : edges){
      REP(tt,2){
        if(par[u] == v){
          fixadj[u].push_back({v,{d,altdist[u]}});
        } else {
          fixadj[u].push_back({v,{d,d+dist[v]}});
        }
        swap(u,v);
      }
    }

    nega_queue<pair<ll,ll>> que;

    while(ng + 1 < ok){
      ll m = ng + (ok - ng) / 2;
      V<ll> dist2(N,INF);
      auto see = [&](ll v, ll d) -> void {
        if(d >= dist2[v]) return;
        que.push({ d, v });
        dist2[v] = d;
      };
      see(S, 0);
      while(que.size()){
        auto [d,v] = que.top(); que.pop();
        if(dist2[v] != d) continue;
        for(auto [w,dd] : fixadj[v]){
          auto [e,off] = dd;
          if(d + off > m) continue;
          see(w, d+e);
        }
      }

      (dist2[T] < INF / 2 ? ok : ng) = m;
    }
  }

  if(ok > INF / 4) ok = -1;
  
  cout << ok << "\n";

}

int main(){
  cin.tie(0)->sync_with_stdio(0);
  testcase();
  return 0;
}
accuracy: 1
time_ms: 510
memory_kb: 62052
final_rank: 5

code_snippet: #include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

#define maxn 100010
#define maxm 800010
typedef long long ll;
struct Edge {
	Edge *next;
	int to, w;
} *last[maxn], e[maxm], *ecnt = e;
inline void link(int a, int b, int w)
{
	*++ecnt = (Edge) {last[a], b, w}; last[a] = ecnt;
	*++ecnt = (Edge) {last[b], a, w}; last[b] = ecnt;
}
ll d[maxn];
int fa[maxn];
int n, m, s, t;
ll f[maxn];
struct Node *null;
struct Node {
	Node *ch[2];
	ll val, tag;
	int lca;
	inline void set_tag(ll tg)
	{
		val += tg;
		tag += tg;
	}
	inline void pushdown()
	{
		if (tag)
		{
			if (ch[0] != null) ch[0] -> set_tag(tag);
			if (ch[1] != null) ch[1] -> set_tag(tag);
			tag = 0;
		}
	}
} *root[maxn], mem[maxm], *tot = mem;
Node *merge(Node *a, Node *b)
{
	if (a == mem) return b;
	if (b == mem) return a;
	if (a -> val > b -> val) std::swap(a, b);
	a -> pushdown();
	std::swap(a -> ch[0], a -> ch[1]);
	a -> ch[1] = merge(a -> ch[1], b);
	return a;
}
int son[maxn], size[maxn], top[maxn], dep[maxn], inv[maxn], dfn[maxn], timer;
void dfs1(int x)
{
	size[x] = 1; dep[x] = dep[fa[x]] + 1;
	for (Edge *iter = last[x]; iter; iter = iter -> next)
		if (fa[iter -> to] == x)
		{
			dfs1(iter -> to);
			size[x] += size[iter -> to];
			size[iter -> to] > size[son[x]] ? son[x] = iter -> to : 0;
		}
}
void dfs2(int x)
{
	top[x] = son[fa[x]] == x ? top[fa[x]] : x;
	dfn[x] = ++timer;
	for (Edge *iter = last[x]; iter; iter = iter -> next)
		if (fa[iter -> to] == x) dfs2(iter -> to);
	inv[x] = timer;
}
inline int getlca(int a, int b)
{
	while (top[a] != top[b])
		dep[top[a]] < dep[top[b]]
			? b = fa[top[b]]
			: a = fa[top[a]];
	return dep[a] < dep[b] ? a : b;
}
void dfs(int x)
{
	root[x] = mem;
	for (Edge *iter = last[x]; iter; iter = iter -> next)
		if (fa[iter -> to] == x)
		{
			dfs(iter -> to);
			if (root[iter -> to] != null) root[iter -> to] -> set_tag(iter -> w);
			root[x] = merge(root[x], root[iter -> to]);
		}
		else if (iter -> to != fa[x])
		{
			*++tot = (Node) {{mem, mem}, d[iter -> to] + iter -> w, 0, getlca(x, iter -> to)};
			root[x] = merge(root[x], tot);
		}
	while (root[x] != null && dfn[x] <= dfn[root[x] -> lca] && dfn[root[x] -> lca] <= inv[x])
		root[x] = merge(root[x] -> ch[0], root[x] -> ch[1]);
	f[x] = root[x] -> val;
}
struct Queue {
	ll d; int x;
	inline bool operator < (const Queue &that) const {return d > that.d;}
} ;
std::priority_queue<Queue> q;
inline bool check(ll mid)
{
	 memset(d, 63, sizeof (d));
	 const ll inf = d[0];
	 q.push((Queue) {d[s] = 0, s});
	 while (!q.empty())
	 {
	 	Queue now = q.top(); q.pop();
	 	if (now.d != d[now.x]) continue;
	 	int x = now.x;
	 	if (d[x] + f[x] > mid) continue;
	 	for (Edge *iter = last[x]; iter; iter = iter -> next)
	 		if (d[iter -> to] > d[x] + iter -> w)
	 		{
	 			d[iter -> to] = d[x] + iter -> w;
	 			q.push((Queue) {d[iter -> to], iter -> to});
	 		}
	 }
	 return d[t] != inf;
}
int main()
{
	null = mem; mem -> val = ~0ULL >> 3; mem -> ch[0] = mem -> ch[1] = mem;
	scanf("%d%d%d%d", &n, &m, &s, &t);
	for (int i = 1; i <= m; ++i)
	{
		int a, b, w; scanf("%d%d%d", &a, &b, &w);
		link(a, b, w);
	}
	memset(d, 63, sizeof (d));
	q.push((Queue) {d[t] = 0, t});
	while (!q.empty())
	{
		Queue now = q.top(); q.pop();
		if (now.d != d[now.x]) continue;
		int x = now.x;
		for (Edge *iter = last[x]; iter; iter = iter -> next)
			if (d[iter -> to] > d[x] + iter -> w)
			{
				d[iter -> to] = d[x] + iter -> w;
				q.push((Queue) {d[iter -> to], iter -> to});
			}
	}

	for (int i = 1; i <= n; ++i)
		for (Edge *iter = last[i]; iter; iter = iter -> next)
			if (d[iter -> to] == d[i] + iter -> w)
				fa[iter -> to] = i;

	dfs1(t);
	dfs2(t);
	dfs(t);
//	for (int i = 1; i <= n; ++i) printf("%lld\n", f[i]);
	ll left = 0, right = 1e18;
	while (left < right)
	{
		ll mid = left + right >> 1;
		if (check(mid)) right = mid;
		else left = mid + 1;
	}
	printf("%lld\n", left > 1e17 ? -1 : left);
	return 0;
}
accuracy: 1
time_ms: 540
memory_kb: 26072
final_rank: 2

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005
#define SIZE_V 100005


struct Edge{
	Edge(){

		from = to = 0;
		cost = 0;
	}
	Edge(int arg_from,int arg_to,ll arg_cost){
		from = arg_from;
		to = arg_to;
		cost = arg_cost;
	}
	bool operator<(const struct Edge &arg) const{

		return cost < arg.cost;
	}
	int from,to;
	ll cost;
};

struct Info{
	Info(int arg_to,int arg_edge_index){
		to = arg_to;
		edge_index = arg_edge_index;
	}
	int to,edge_index;
};

struct State{
	State(int arg_node_id,ll arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の昇順(PQ)
	}
	int node_id;
	ll sum_dist;
};

struct Data{
	Data(int arg_pre_node,int arg_pre_edge){
		pre_node = arg_pre_node;
		pre_edge = arg_pre_edge;
	}
	int pre_node,pre_edge;
};

struct Data2{
	Data2(int arg_from,int arg_to, ll arg_value){
		from = arg_from;
		to = arg_to;
		value = arg_value;
	}
	bool operator<(const struct Data2 &arg) const{

		return value < arg.value;
	}

	int from,to;
	ll value;
};


int N,E;
int start,goal;
ll COST[SIZE],not_COST[SIZE];
ll min_dist[SIZE],work_dist[SIZE];
Edge edge[SIZE];

vector<Info> G[SIZE_V],rev_G[SIZE_V];
int root; //根ノードの番号
int MAX_LOG_V = 17;
int POW[18];

int parent[18][SIZE_V],calc_parent[SIZE_V];
int depth[SIZE_V];
vector<Data> D[SIZE_V];
bool is_minPath[SIZE];



//parentとdepthを再帰的に設定
void dfs(int node_id,int parent_id,int d){
	parent[0][node_id] = parent_id;
	depth[node_id] = d;
	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to != parent_id)dfs(G[node_id][i].to,node_id,d+1);
	}
}


void init(){

	dfs(root,-1,0);

	for(int k = 0; k + 1 < MAX_LOG_V; k++){
		for(int node_id = 0; node_id < N; node_id++){
			if(parent[k][node_id] < 0)parent[k+1][node_id] = -1;
			else{
				parent[k+1][node_id] = parent[k][parent[k][node_id]];
			}
		}
	}
}


int lca(int left,int right){

	if(depth[left] > depth[right])swap(left,right);

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(depth[right]-depth[left] >= POW[k]){
			right = parent[k][right];
		}
	}

	if(left == right)return left;

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(parent[k][left] == parent[k][right]){
			//Do nothing
		}else{
			left = parent[k][left];
			right = parent[k][right];
		}
	}
	return parent[0][left];
}

bool is_OK(ll worst_dist){

	for(int i = 0; i < N; i++){

		work_dist[i] = HUGE_NUM;
	}

	priority_queue<State> Q;
	work_dist[start] = 0;

	Q.push(State(start,0));

	int next_node;
	ll next_cost;

	while(!Q.empty()){

		if(Q.top().sum_dist > work_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < rev_G[Q.top().node_id].size(); i++){

				next_node = rev_G[Q.top().node_id][i].to;
				if(is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+not_COST[Q.top().node_id] > worst_dist){

					continue;
				}
				if(!is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+min_dist[Q.top().node_id] > worst_dist){

					continue;
				}

				next_cost = work_dist[Q.top().node_id]+COST[rev_G[Q.top().node_id][i].edge_index];
				if(work_dist[next_node] > next_cost){
					work_dist[next_node] = next_cost;
					Q.push(State(next_node,next_cost));
				}
			}
			Q.pop();
		}
	}

	return work_dist[goal] <= worst_dist;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 18; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d %d %d",&N,&E,&start,&goal);
	start--;
	goal--;

	ll sum_cost = 0;

	for(int i = 0; i < E; i++){

		scanf("%d %d %lld",&edge[i].from,&edge[i].to,&edge[i].cost);
		edge[i].from--;
		edge[i].to--;

		COST[i] = edge[i].cost;
		sum_cost += COST[i];
		G[edge[i].from].push_back(Info(edge[i].to,i));
		G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	for(int i = 0; i < N; i++){

		min_dist[i] = HUGE_NUM;
	}

	min_dist[goal] = 0;
	priority_queue<State> Q;
	Q.push(State(goal,0));

	int next_node;
	ll next_dist;

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){

				next_node = G[Q.top().node_id][i].to;
				next_dist = min_dist[Q.top().node_id]+COST[G[Q.top().node_id][i].edge_index];

				if(min_dist[next_node] > next_dist){

					D[next_node].clear();
					D[next_node].push_back(Data(Q.top().node_id,G[Q.top().node_id][i].edge_index));
					min_dist[next_node] = next_dist;
					Q.push(State(next_node,next_dist));

				}
			}

			Q.pop();
		}
	}

	//最短経路木を構築
	for(int i = 0; i < N; i++){

		G[i].clear();
	}
	for(int i = 0; i < E; i++){

		is_minPath[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(i == goal)continue;

		for(int k = 0; k < D[i].size(); k++){

			is_minPath[D[i][k].pre_edge] = true;
			G[D[i][k].pre_node].push_back(Info(i,D[i][k].pre_edge)); //goal→start方向
		}
	}

	root = goal;
	init();

	for(int i = 0; i < N; i++){

		calc_parent[i] = parent[0][i];
		not_COST[i] = HUGE_NUM;
	}

	vector<Data2> vec;
	for(int i = 0; i < E; i++){
		if(is_minPath[i])continue;

		vec.push_back(Data2(edge[i].from,edge[i].to,edge[i].cost+min_dist[edge[i].from]+min_dist[edge[i].to])); //総コストの昇順にする
	}

	sort(vec.begin(),vec.end());

	for(int i = 0; i < vec.size(); i++){

		int a = vec[i].from;
		int b = vec[i].to;

		int LCM = lca(a,b);

		ll value = vec[i].value;

		if(depth[a] <= depth[b]){ //aの方を深くする

			swap(a,b);
		}

		while(true){

			if(depth[a] <= depth[LCM])break;

			if(not_COST[a] > value){

				not_COST[a] = value;
			}

			next_node = calc_parent[a];
			calc_parent[a] = LCM; //経路圧縮
			a = next_node;
		}

		while(true){

			if(depth[b] <= depth[LCM])break;

			if(not_COST[b] > value){

				not_COST[b] = value;
			}

			next_node = calc_parent[b];
			calc_parent[b] = LCM;
			b = next_node;
		}
	}

	for(int i = 0; i < N; i++){

		not_COST[i] -= min_dist[i];
	}

	for(int i = 0; i < E; i++){

		rev_G[edge[i].from].push_back(Info(edge[i].to,i));
		rev_G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	ll left = min_dist[start],right = HUGE_NUM/100,mid = (left+right)/2;
	ll ans = HUGE_NUM;


	while(left <= right){

		if(is_OK(mid)){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == HUGE_NUM){

		printf("-1\n");
	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 600
memory_kb: 46056
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

// Variables: Input
long long N, M, S, T;
long long A[200009], B[200009], C[200009];
vector<pair<long long, long long>> G[200009];

// Variables: Dist
bool used[200009];
long long dist[200009];
long long distS[200009], distT[200009];
long long par[200009];
vector<long long> H[200009];

// DFS-Tree
long long root[200009];
long long Offset[200009];
vector<pair<long long, long long>> Add[200009];
map<pair<long long, long long>, int> Map[200009];

void dfs(int pos) {
	// Initialize
	for (int i = 0; i < (int)H[pos].size(); i++) {
		dfs(H[pos][i]);
	}
	
	// Get Largest
	int maxn = -1, maxid = pos;
	for (int i = 0; i < (int)H[pos].size(); i++) {
		int sz = Map[root[H[pos][i]]].size();
		if (maxn < sz) {
			maxn = sz;
			maxid = H[pos][i];
		}
	}
	
	// Merge Tech
	root[pos] = root[maxid];
	for (int i = 0; i < (int)H[pos].size(); i++) {
		int to = H[pos][i]; if (to == maxid) continue;
		auto itr = Map[root[to]].begin();
		while (itr != Map[root[to]].end()) {
			pair<long long, long long> val = (*itr).first;
			Map[root[pos]][val] += 1;
			if (Map[root[pos]][val] == 2) Map[root[pos]].erase(val);
			itr++;
		}
	}
	
	// Add Edges
	for (int i = 0; i < (int)Add[pos].size(); i++) {
		pair<long long, long long> KEY = Add[pos][i];
		Map[root[pos]][KEY] += 1;
		if (Map[root[pos]][KEY] == 2) Map[root[pos]].erase(KEY);
	}
	
	// Get Offset
	long long ret = (1LL << 60);
	if (Map[root[pos]].size() >= 1) {
		auto itr = Map[root[pos]].begin();
		ret = ((*itr).first).first;
	}
	if (pos != T) {
		if (ret == (1LL << 60)) Offset[pos] = (1LL << 60);
		else Offset[pos] = ret - distT[pos];
	}
}

bool dijkstra(int stt, int Mode, long long Border) {
	priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> Q;
	for (int i = 1; i <= N; i++) dist[i] = (1LL << 60);
	for (int i = 1; i <= N; i++) used[i] = false;
	
	// Dijkstra Start
	if (Mode == 1 || Border - Offset[stt] >= 0LL) {
		dist[stt] = 0;
		Q.push(make_pair(0, stt));
	}
	while(!Q.empty()) {
		int pos = Q.top().second; Q.pop();
		if (used[pos] == true) continue;
		used[pos] = true;
		for (int i = 0; i < (int)G[pos].size(); i++) {
			long long to = G[pos][i].first;
			long long cost = G[pos][i].second;
			
			// Mode 2 Case
			if (Mode == 2 && (dist[pos] + cost) > (Border - Offset[to])) continue;
			//cout << Border << ": " << pos << " " << dist[pos] + cost << " " << Border - Offset[to] << endl;
			
			// Transition
			if (dist[to] > dist[pos] + cost) {
				dist[to] = dist[pos] + cost;
				Q.push(make_pair(dist[to], to));
			}
		}
	}
	
	// Return
	if (Mode == 2 && dist[T] == (1LL << 60)) return false;
	return true;
}

int main() {
	// Input
	cin >> N >> M >> S >> T;
	for (int i = 1; i <= M; i++) {
		cin >> A[i] >> B[i] >> C[i];
		G[A[i]].push_back(make_pair(B[i], C[i]));
		G[B[i]].push_back(make_pair(A[i], C[i]));
	}
	
	// Get Distance from S, T
	dijkstra(S, 1, -1);
	for (int i = 1; i <= N; i++) distS[i] = dist[i];
	dijkstra(T, 1, -1);
	for (int i = 1; i <= N; i++) distT[i] = dist[i];
	
	// Make shortest-path Tree
	for (int i = 1; i <= N; i++) {
		par[i] = -1;
		for (int j = 0; j < (int)G[i].size(); j++) {
			long long to = G[i][j].first;
			long long cost = G[i][j].second;
			if (distT[to] == distT[i] - cost) par[i] = to;
		}
		if (par[i] != -1) H[par[i]].push_back(i);
	}
	
	// Prepare 1
	for (int i = 1; i <= M; i++) {
		if (distT[A[i]] < distT[B[i]]) swap(A[i], B[i]);
		if (par[A[i]] != B[i]) {
			long long ret = distT[A[i]] + distT[B[i]] + C[i];
			Add[A[i]].push_back(make_pair(ret, i));
			Add[B[i]].push_back(make_pair(ret, i));
			//cout << i << " " << A[i] << " " << B[i] <<  " " << ret << endl;
		}
	}
	
	// DFS in shortest-path Tree
	for (int i = 1; i <= N; i++) root[i] = i;
	dfs(T);
	//for (int i = 1; i <= N; i++) cout << Offset[i] << " "; cout << endl;
	
	// Getting Final Answer
	long long cl = 0, cr = (1LL << 60), cm, Answer = (1LL << 60);
	for (int i = 0; i < 70; i++) {
		cm = (cl + cr) / 2LL;
		bool ret = dijkstra(S, 2, cm);
		if (ret == true) { cr = cm; Answer = min(Answer, cm); }
		else { cl = cm; }
	}
	
	// Output
	if (Answer == (1LL << 60)) cout << "-1" << endl;
	else cout << Answer << endl;
	return 0;
}
accuracy: 1
time_ms: 900
memory_kb: 108400
final_rank: 9

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005
#define SIZE_V 100005


struct Edge{
	Edge(){

		from = to = 0;
		cost = 0;
	}
	Edge(int arg_from,int arg_to,ll arg_cost){
		from = arg_from;
		to = arg_to;
		cost = arg_cost;
	}
	bool operator<(const struct Edge &arg) const{

		return cost < arg.cost;
	}
	int from,to;
	ll cost;
};

struct Info{
	Info(int arg_to,int arg_edge_index){
		to = arg_to;
		edge_index = arg_edge_index;
	}
	int to,edge_index;
};

struct State{
	State(int arg_node_id,ll arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の昇順(PQ)
	}
	int node_id;
	ll sum_dist;
};

struct Data{
	Data(int arg_pre_node,int arg_pre_edge){
		pre_node = arg_pre_node;
		pre_edge = arg_pre_edge;
	}
	int pre_node,pre_edge;
};

struct Data2{
	Data2(int arg_from,int arg_to, ll arg_value){
		from = arg_from;
		to = arg_to;
		value = arg_value;
	}
	bool operator<(const struct Data2 &arg) const{

		return value < arg.value;
	}

	int from,to;
	ll value;
};


int N,E;
int start,goal;
ll COST[SIZE],not_COST[SIZE];
ll min_dist[SIZE],work_dist[SIZE];
Edge edge[SIZE];

vector<Info> G[SIZE_V],rev_G[SIZE_V];
int root; //根ノードの番号
int MAX_LOG_V = 17;
int POW[18];

int parent[18][SIZE_V],calc_parent[SIZE_V];
int depth[SIZE_V];
vector<Data> D[SIZE_V];
bool is_minPath[SIZE];



//parentとdepthを再帰的に設定
void dfs(int node_id,int parent_id,int d){
	parent[0][node_id] = parent_id;
	depth[node_id] = d;
	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to != parent_id)dfs(G[node_id][i].to,node_id,d+1);
	}
}


void init(){

	dfs(root,-1,0);

	for(int k = 0; k + 1 < MAX_LOG_V; k++){
		for(int node_id = 0; node_id < N; node_id++){
			if(parent[k][node_id] < 0)parent[k+1][node_id] = -1;
			else{
				parent[k+1][node_id] = parent[k][parent[k][node_id]];
			}
		}
	}
}


int lca(int left,int right){

	if(depth[left] > depth[right])swap(left,right);

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(depth[right]-depth[left] >= POW[k]){
			right = parent[k][right];
		}
	}

	if(left == right)return left;

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(parent[k][left] == parent[k][right]){
			//Do nothing
		}else{
			left = parent[k][left];
			right = parent[k][right];
		}
	}
	return parent[0][left];
}

bool is_OK(ll worst_dist){

	for(int i = 0; i < N; i++){

		work_dist[i] = HUGE_NUM;
	}

	priority_queue<State> Q;
	work_dist[start] = 0;

	Q.push(State(start,0));

	int next_node;
	ll next_cost;

	while(!Q.empty()){

		if(Q.top().sum_dist > work_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < rev_G[Q.top().node_id].size(); i++){

				next_node = rev_G[Q.top().node_id][i].to;
				if(is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+not_COST[Q.top().node_id] > worst_dist){

					continue;
				}
				if(!is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+min_dist[Q.top().node_id] > worst_dist){

					continue;
				}

				next_cost = work_dist[Q.top().node_id]+COST[rev_G[Q.top().node_id][i].edge_index];
				if(work_dist[next_node] > next_cost){
					work_dist[next_node] = next_cost;
					Q.push(State(next_node,next_cost));
				}
			}
			Q.pop();
		}
	}

	return work_dist[goal] <= worst_dist;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 18; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d %d %d",&N,&E,&start,&goal);
	start--;
	goal--;

	ll sum_cost = 0;

	for(int i = 0; i < E; i++){

		scanf("%d %d %lld",&edge[i].from,&edge[i].to,&edge[i].cost);
		edge[i].from--;
		edge[i].to--;

		COST[i] = edge[i].cost;
		sum_cost += COST[i];
		G[edge[i].from].push_back(Info(edge[i].to,i));
		G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	for(int i = 0; i < N; i++){

		min_dist[i] = HUGE_NUM;
	}

	min_dist[goal] = 0;
	priority_queue<State> Q;
	Q.push(State(goal,0));

	int next_node;
	ll next_dist;

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){

				next_node = G[Q.top().node_id][i].to;
				next_dist = min_dist[Q.top().node_id]+COST[G[Q.top().node_id][i].edge_index];

				if(min_dist[next_node] > next_dist){

					D[next_node].clear();
					D[next_node].push_back(Data(Q.top().node_id,G[Q.top().node_id][i].edge_index));
					min_dist[next_node] = next_dist;
					Q.push(State(next_node,next_dist));

				}
			}

			Q.pop();
		}
	}

	//最短経路木を構築
	for(int i = 0; i < N; i++){

		G[i].clear();
	}
	for(int i = 0; i < E; i++){

		is_minPath[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(i == goal)continue;

		for(int k = 0; k < D[i].size(); k++){

			is_minPath[D[i][k].pre_edge] = true;
			G[D[i][k].pre_node].push_back(Info(i,D[i][k].pre_edge)); //goal→start方向
		}
	}

	root = goal;
	init();

	for(int i = 0; i < N; i++){

		calc_parent[i] = parent[0][i];
		not_COST[i] = HUGE_NUM;
	}

	vector<Data2> vec;
	for(int i = 0; i < E; i++){
		if(is_minPath[i])continue;

		vec.push_back(Data2(edge[i].from,edge[i].to,edge[i].cost+min_dist[edge[i].from]+min_dist[edge[i].to])); //総コストの昇順にする
	}

	sort(vec.begin(),vec.end());

	for(int i = 0; i < vec.size(); i++){

		int a = vec[i].from;
		int b = vec[i].to;

		int LCM = lca(a,b);

		ll value = vec[i].value;

		if(depth[a] <= depth[b]){ //aの方を深くする

			swap(a,b);
		}

		while(true){

			if(depth[a] <= depth[LCM])break;

			if(not_COST[a] > value){

				not_COST[a] = value;
			}

			next_node = calc_parent[a];
			calc_parent[a] = LCM; //経路圧縮
			a = next_node;
		}

		while(true){

			if(depth[b] <= depth[LCM])break;

			if(not_COST[b] > value){

				not_COST[b] = value;
			}

			next_node = calc_parent[b];
			calc_parent[b] = LCM;
			b = next_node;
		}
	}

	for(int i = 0; i < N; i++){

		not_COST[i] -= min_dist[i];
	}

	for(int i = 0; i < E; i++){

		rev_G[edge[i].from].push_back(Info(edge[i].to,i));
		rev_G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	ll left = min_dist[start],right = HUGE_NUM/100,mid = (left+right)/2;
	ll ans = HUGE_NUM;


	while(left <= right){

		if(is_OK(mid)){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == HUGE_NUM){

		printf("-1\n");
	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 810
memory_kb: 42952
final_rank: 6

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005
#define SIZE_V 100005


struct Edge{
	Edge(){

		from = to = 0;
		cost = 0;
	}
	Edge(int arg_from,int arg_to,ll arg_cost){
		from = arg_from;
		to = arg_to;
		cost = arg_cost;
	}
	bool operator<(const struct Edge &arg) const{

		return cost < arg.cost;
	}
	int from,to;
	ll cost;
};

struct Info{
	Info(int arg_to,int arg_edge_index){
		to = arg_to;
		edge_index = arg_edge_index;
	}
	int to,edge_index;
};

struct State{
	State(int arg_node_id,ll arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の昇順(PQ)
	}
	int node_id;
	ll sum_dist;
};

struct Data{
	Data(int arg_pre_node,int arg_pre_edge){
		pre_node = arg_pre_node;
		pre_edge = arg_pre_edge;
	}
	int pre_node,pre_edge;
};

struct Data2{
	Data2(int arg_from,int arg_to, ll arg_value){
		from = arg_from;
		to = arg_to;
		value = arg_value;
	}
	bool operator<(const struct Data2 &arg) const{

		return value < arg.value;
	}

	int from,to;
	ll value;
};


int N,E;
int start,goal;
ll COST[SIZE],not_COST[SIZE];
ll min_dist[SIZE],work_dist[SIZE];
Edge edge[SIZE];

vector<Info> G[SIZE_V],rev_G[SIZE_V];
int root; //根ノードの番号
int MAX_LOG_V = 17;
int POW[18];

int parent[18][SIZE_V],calc_parent[SIZE_V];
int depth[SIZE_V];
vector<Data> D[SIZE_V];
bool is_minPath[SIZE];



//parentとdepthを再帰的に設定
void dfs(int node_id,int parent_id,int d){
	parent[0][node_id] = parent_id;
	depth[node_id] = d;
	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to != parent_id)dfs(G[node_id][i].to,node_id,d+1);
	}
}


void init(){

	dfs(root,-1,0);

	for(int k = 0; k + 1 < MAX_LOG_V; k++){
		for(int node_id = 0; node_id < N; node_id++){
			if(parent[k][node_id] < 0)parent[k+1][node_id] = -1;
			else{
				parent[k+1][node_id] = parent[k][parent[k][node_id]];
			}
		}
	}
}


int lca(int left,int right){

	if(depth[left] > depth[right])swap(left,right);

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(depth[right]-depth[left] >= POW[k]){
			right = parent[k][right];
		}
	}

	if(left == right)return left;

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(parent[k][left] == parent[k][right]){
			//Do nothing
		}else{
			left = parent[k][left];
			right = parent[k][right];
		}
	}
	return parent[0][left];
}

bool is_OK(ll worst_dist){

	for(int i = 0; i < N; i++){

		work_dist[i] = HUGE_NUM;
	}

	priority_queue<State> Q;
	work_dist[start] = 0;

	Q.push(State(start,0));

	int next_node;
	ll next_cost;

	while(!Q.empty()){

		//printf("node_id:%d cost:%lld\n",Q.top().node_id,Q.top().sum_dist);

		if(Q.top().sum_dist > work_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < rev_G[Q.top().node_id].size(); i++){

				next_node = rev_G[Q.top().node_id][i].to;
				if(is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+not_COST[Q.top().node_id] > worst_dist){

					continue;
				}
				if(!is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+min_dist[Q.top().node_id] > worst_dist){

					continue;
				}

				next_cost = work_dist[Q.top().node_id]+COST[rev_G[Q.top().node_id][i].edge_index];
				if(work_dist[next_node] > next_cost){
					work_dist[next_node] = next_cost;
					Q.push(State(next_node,next_cost));
				}
			}
			Q.pop();
		}
	}

	return work_dist[goal] <= worst_dist;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 18; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d %d %d",&N,&E,&start,&goal);
	start--;
	goal--;

	ll sum_cost = 0;

	for(int i = 0; i < E; i++){

		scanf("%d %d %lld",&edge[i].from,&edge[i].to,&edge[i].cost);
		edge[i].from--;
		edge[i].to--;

		COST[i] = edge[i].cost;
		sum_cost += COST[i];
		G[edge[i].from].push_back(Info(edge[i].to,i));
		G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	for(int i = 0; i < N; i++){

		min_dist[i] = HUGE_NUM;
	}

	min_dist[goal] = 0;
	priority_queue<State> Q;
	Q.push(State(goal,0));

	int next_node;
	ll next_dist;

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){

				next_node = G[Q.top().node_id][i].to;
				next_dist = min_dist[Q.top().node_id]+COST[G[Q.top().node_id][i].edge_index];

				if(min_dist[next_node] > next_dist){

					D[next_node].clear();
					D[next_node].push_back(Data(Q.top().node_id,G[Q.top().node_id][i].edge_index));
					min_dist[next_node] = next_dist;
					Q.push(State(next_node,next_dist));

				}
			}

			Q.pop();
		}
	}
/*
	for(int i = 0; i < N; i++){

		printf("i:%d min_dist:%lld\n",i,min_dist[i]);
	}*/

	//最短経路木を構築
	for(int i = 0; i < N; i++){

		G[i].clear();
	}
	for(int i = 0; i < E; i++){

		is_minPath[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(i == goal)continue;

		for(int k = 0; k < D[i].size(); k++){

			is_minPath[D[i][k].pre_edge] = true;
			G[D[i][k].pre_node].push_back(Info(i,D[i][k].pre_edge)); //goal→start方向
		}
	}

	root = goal;
	init();

	for(int i = 0; i < N; i++){

		calc_parent[i] = parent[0][i];
		not_COST[i] = HUGE_NUM;
	}

	vector<Data2> vec;
	for(int i = 0; i < E; i++){
		if(is_minPath[i])continue;

		vec.push_back(Data2(edge[i].from,edge[i].to,edge[i].cost+min_dist[edge[i].from]+min_dist[edge[i].to]));
	}

	sort(vec.begin(),vec.end());

	for(int i = 0; i < vec.size(); i++){

		int a = vec[i].from;
		int b = vec[i].to;

		int LCM = lca(a,b);

		//printf("a:%d b:%d LCM:%d\n",a,b,LCM);

		ll value = vec[i].value;

		if(depth[a] <= depth[b]){

			swap(a,b);
		}

		while(true){

			if(depth[a] <= depth[LCM])break;

			if(not_COST[a] > value){

				not_COST[a] = value;
			}

			//next_node = parent[0][a];
			next_node = calc_parent[a];
			calc_parent[a] = LCM;
			a = next_node;
		}

		while(true){

			if(depth[b] <= depth[LCM])break;

			if(not_COST[b] > value){

				not_COST[b] = value;
			}

			//next_node = parent[0][b];
			next_node = calc_parent[b];
			calc_parent[b] = LCM;
			b = next_node;
		}
	}

	for(int i = 0; i < N; i++){

		not_COST[i] -= min_dist[i];
		//printf("not_COST[%d]:%lld\n",i,not_COST[i]);
	}

	//printf("sum_cost:%lld\n",sum_cost);

	for(int i = 0; i < E; i++){

		rev_G[edge[i].from].push_back(Info(edge[i].to,i));
		rev_G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	ll left = min_dist[start],right = HUGE_NUM/100,mid = (left+right)/2;
	ll ans = HUGE_NUM;

	//printf("min_dist[start]:%lld\n",min_dist[start]);

	while(left <= right){

		if(is_OK(mid)){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == HUGE_NUM){

		printf("-1\n");
	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 820
memory_kb: 42952
final_rank: 7

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005
#define SIZE_V 100005


struct Edge{
	Edge(){

		from = to = 0;
		cost = 0;
	}
	Edge(int arg_from,int arg_to,ll arg_cost){
		from = arg_from;
		to = arg_to;
		cost = arg_cost;
	}
	bool operator<(const struct Edge &arg) const{

		return cost < arg.cost;
	}
	int from,to;
	ll cost;
};

struct Info{
	Info(int arg_to,int arg_edge_index){
		to = arg_to;
		edge_index = arg_edge_index;
	}
	int to,edge_index;
};

struct State{
	State(int arg_node_id,ll arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の昇順(PQ)
	}
	int node_id;
	ll sum_dist;
};

struct Data{
	Data(int arg_pre_node,int arg_pre_edge){
		pre_node = arg_pre_node;
		pre_edge = arg_pre_edge;
	}
	int pre_node,pre_edge;
};


int N,E;
int start,goal;
ll COST[SIZE],not_COST[SIZE];
ll min_dist[SIZE],work_dist[SIZE];
Edge edge[SIZE];

vector<Info> G[SIZE_V],rev_G[SIZE_V];
int root; //根ノードの番号
int MAX_LOG_V = 17;
int POW[18];

int parent[18][SIZE_V],calc_parent[SIZE_V];
int depth[SIZE_V];
vector<Data> D[SIZE_V];
bool is_minPath[SIZE];



//parentとdepthを再帰的に設定
void dfs(int node_id,int parent_id,int d){
	parent[0][node_id] = parent_id;
	depth[node_id] = d;
	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to != parent_id)dfs(G[node_id][i].to,node_id,d+1);
	}
}


void init(){

	dfs(root,-1,0);

	for(int k = 0; k + 1 < MAX_LOG_V; k++){
		for(int node_id = 0; node_id < N; node_id++){
			if(parent[k][node_id] < 0)parent[k+1][node_id] = -1;
			else{
				parent[k+1][node_id] = parent[k][parent[k][node_id]];
			}
		}
	}
}


int lca(int left,int right){

	if(depth[left] > depth[right])swap(left,right);

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(depth[right]-depth[left] >= POW[k]){
			right = parent[k][right];
		}
	}

	if(left == right)return left;

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(parent[k][left] == parent[k][right]){
			//Do nothing
		}else{
			left = parent[k][left];
			right = parent[k][right];
		}
	}
	return parent[0][left];
}

bool is_OK(ll worst_dist){

	for(int i = 0; i < N; i++){

		work_dist[i] = HUGE_NUM;
	}

	priority_queue<State> Q;
	work_dist[start] = 0;

	Q.push(State(start,0));

	int next_node;
	ll next_cost;

	while(!Q.empty()){

		//printf("node_id:%d cost:%lld\n",Q.top().node_id,Q.top().sum_dist);

		if(Q.top().sum_dist > work_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < rev_G[Q.top().node_id].size(); i++){

				next_node = rev_G[Q.top().node_id][i].to;
				if(is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+not_COST[Q.top().node_id] > worst_dist){

					continue;
				}
				if(!is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+min_dist[Q.top().node_id] > worst_dist){

					continue;
				}

				next_cost = work_dist[Q.top().node_id]+COST[rev_G[Q.top().node_id][i].edge_index];
				if(work_dist[next_node] > next_cost){
					work_dist[next_node] = next_cost;
					Q.push(State(next_node,next_cost));
				}
			}
			Q.pop();
		}
	}

	return work_dist[goal] <= worst_dist;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 18; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d %d %d",&N,&E,&start,&goal);
	start--;
	goal--;

	ll sum_cost = 0;

	for(int i = 0; i < E; i++){

		scanf("%d %d %lld",&edge[i].from,&edge[i].to,&edge[i].cost);
		edge[i].from--;
		edge[i].to--;

		COST[i] = edge[i].cost;
		sum_cost += COST[i];
		G[edge[i].from].push_back(Info(edge[i].to,i));
		G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	for(int i = 0; i < N; i++){

		min_dist[i] = HUGE_NUM;
	}

	min_dist[goal] = 0;
	priority_queue<State> Q;
	Q.push(State(goal,0));

	int next_node;
	ll next_dist;

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){

				next_node = G[Q.top().node_id][i].to;
				next_dist = min_dist[Q.top().node_id]+COST[G[Q.top().node_id][i].edge_index];

				if(min_dist[next_node] > next_dist){

					D[next_node].clear();
					D[next_node].push_back(Data(Q.top().node_id,G[Q.top().node_id][i].edge_index));
					min_dist[next_node] = next_dist;
					Q.push(State(next_node,next_dist));

				}
			}

			Q.pop();
		}
	}
/*
	for(int i = 0; i < N; i++){

		printf("i:%d min_dist:%lld\n",i,min_dist[i]);
	}*/

	//最短経路木を構築
	for(int i = 0; i < N; i++){

		G[i].clear();
	}
	for(int i = 0; i < E; i++){

		is_minPath[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(i == goal)continue;

		for(int k = 0; k < D[i].size(); k++){

			is_minPath[D[i][k].pre_edge] = true;
			G[D[i][k].pre_node].push_back(Info(i,D[i][k].pre_edge)); //goal→start方向
		}
	}

	root = goal;
	init();

	for(int i = 0; i < N; i++){

		calc_parent[i] = parent[0][i];
		not_COST[i] = HUGE_NUM;
	}

	vector<Edge> vec;
	for(int i = 0; i < E; i++){
		if(is_minPath[i])continue;

		vec.push_back(Edge(edge[i].from,edge[i].to,edge[i].cost));
	}

	sort(vec.begin(),vec.end());

	for(int i = 0; i < vec.size(); i++){

		int a = vec[i].from;
		int b = vec[i].to;

		int LCM = lca(a,b);

		//printf("a:%d b:%d LCM:%d\n",a,b,LCM);

		ll value = min_dist[a]+min_dist[b]+vec[i].cost;

		if(depth[a] <= depth[b]){

			swap(a,b);
		}

		while(true){

			if(depth[a] <= depth[LCM])break;

			if(not_COST[a] > value){

				not_COST[a] = value;
			}

			next_node = parent[0][a];
			//next_node = calc_parent[a];
			//calc_parent[a] = LCM;
			a = next_node;
		}

		while(true){

			if(depth[b] <= depth[LCM])break;

			if(not_COST[b] > value){

				not_COST[b] = value;
			}

			next_node = parent[0][b];
			//next_node = calc_parent[b];
			//calc_parent[b] = LCM;
			b = next_node;
		}
	}

	for(int i = 0; i < N; i++){

		not_COST[i] -= min_dist[i];
		//printf("not_COST[%d]:%lld\n",i,not_COST[i]);
	}

	//printf("sum_cost:%lld\n",sum_cost);

	for(int i = 0; i < E; i++){

		rev_G[edge[i].from].push_back(Info(edge[i].to,i));
		rev_G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	ll left = min_dist[start],right = HUGE_NUM/100,mid = (left+right)/2;
	ll ans = HUGE_NUM;

	//printf("min_dist[start]:%lld\n",min_dist[start]);

	while(left <= right){

		if(is_OK(mid)){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == HUGE_NUM){

		printf("-1\n");
	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 860
memory_kb: 42932
final_rank: 8

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005
#define SIZE_V 100005


struct Edge{
	Edge(){

		from = to = 0;
		cost = 0;
	}
	Edge(int arg_from,int arg_to,ll arg_cost){
		from = arg_from;
		to = arg_to;
		cost = arg_cost;
	}
	bool operator<(const struct Edge &arg) const{

		return cost < arg.cost;
	}
	int from,to;
	ll cost;
};

struct Info{
	Info(int arg_to,int arg_edge_index){
		to = arg_to;
		edge_index = arg_edge_index;
	}
	int to,edge_index;
};

struct State{
	State(int arg_node_id,ll arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の昇順(PQ)
	}
	int node_id;
	ll sum_dist;
};

struct Data{
	Data(int arg_pre_node,int arg_pre_edge){
		pre_node = arg_pre_node;
		pre_edge = arg_pre_edge;
	}
	int pre_node,pre_edge;
};


int N,E;
int start,goal;
ll COST[SIZE],not_COST[SIZE];
ll min_dist[SIZE],work_dist[SIZE];
Edge edge[SIZE];

vector<Info> G[SIZE_V],rev_G[SIZE_V];
int root; //根ノードの番号
int MAX_LOG_V = 17;
int POW[18];

int parent[18][SIZE_V],calc_parent[SIZE_V];
int depth[SIZE_V];
vector<Data> D[SIZE_V];
bool is_minPath[SIZE];



//parentとdepthを再帰的に設定
void dfs(int node_id,int parent_id,int d){
	parent[0][node_id] = parent_id;
	depth[node_id] = d;
	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to != parent_id)dfs(G[node_id][i].to,node_id,d+1);
	}
}


void init(){

	dfs(root,-1,0);

	for(int k = 0; k + 1 < MAX_LOG_V; k++){
		for(int node_id = 0; node_id < N; node_id++){
			if(parent[k][node_id] < 0)parent[k+1][node_id] = -1;
			else{
				parent[k+1][node_id] = parent[k][parent[k][node_id]];
			}
		}
	}
}


int lca(int left,int right){

	if(depth[left] > depth[right])swap(left,right);

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(depth[right]-depth[left] >= POW[k]){
			right = parent[k][right];
		}
	}

	if(left == right)return left;

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(parent[k][left] == parent[k][right]){
			//Do nothing
		}else{
			left = parent[k][left];
			right = parent[k][right];
		}
	}
	return parent[0][left];
}

bool is_OK(ll worst_dist){

	for(int i = 0; i < N; i++){

		work_dist[i] = HUGE_NUM;
	}

	priority_queue<State> Q;
	work_dist[start] = 0;

	Q.push(State(start,0));

	int next_node;
	ll next_cost;

	while(!Q.empty()){

		//printf("node_id:%d cost:%lld\n",Q.top().node_id,Q.top().sum_dist);

		if(Q.top().sum_dist > work_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < rev_G[Q.top().node_id].size(); i++){

				next_node = rev_G[Q.top().node_id][i].to;
				if(is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+not_COST[Q.top().node_id] > worst_dist){

					continue;
				}
				if(!is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+min_dist[Q.top().node_id] > worst_dist){

					continue;
				}

				next_cost = work_dist[Q.top().node_id]+COST[rev_G[Q.top().node_id][i].edge_index];
				if(work_dist[next_node] > next_cost){
					work_dist[next_node] = next_cost;
					Q.push(State(next_node,next_cost));
				}
			}
			Q.pop();
		}
	}

	return work_dist[goal] <= worst_dist;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 18; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d %d %d",&N,&E,&start,&goal);
	start--;
	goal--;

	ll sum_cost = 0;

	for(int i = 0; i < E; i++){

		scanf("%d %d %lld",&edge[i].from,&edge[i].to,&edge[i].cost);
		edge[i].from--;
		edge[i].to--;

		COST[i] = edge[i].cost;
		sum_cost += COST[i];
		G[edge[i].from].push_back(Info(edge[i].to,i));
		G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	for(int i = 0; i < N; i++){

		min_dist[i] = HUGE_NUM;
	}

	min_dist[goal] = 0;
	priority_queue<State> Q;
	Q.push(State(goal,0));

	int next_node;
	ll next_dist;

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){

				next_node = G[Q.top().node_id][i].to;
				next_dist = min_dist[Q.top().node_id]+COST[G[Q.top().node_id][i].edge_index];

				if(min_dist[next_node] > next_dist){

					D[next_node].clear();
					D[next_node].push_back(Data(Q.top().node_id,G[Q.top().node_id][i].edge_index));
					min_dist[next_node] = next_dist;
					Q.push(State(next_node,next_dist));

				}
			}

			Q.pop();
		}
	}
/*
	for(int i = 0; i < N; i++){

		printf("i:%d min_dist:%lld\n",i,min_dist[i]);
	}*/

	//最短経路木を構築
	for(int i = 0; i < N; i++){

		G[i].clear();
	}
	for(int i = 0; i < E; i++){

		is_minPath[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(i == goal)continue;

		for(int k = 0; k < D[i].size(); k++){

			is_minPath[D[i][k].pre_edge] = true;
			G[D[i][k].pre_node].push_back(Info(i,D[i][k].pre_edge)); //goal→start方向
		}
	}

	root = goal;
	init();

	for(int i = 0; i < N; i++){

		calc_parent[i] = parent[0][i];
		not_COST[i] = HUGE_NUM;
	}

	vector<Edge> vec;
	for(int i = 0; i < E; i++){
		if(is_minPath[i])continue;

		vec.push_back(Edge(edge[i].from,edge[i].to,edge[i].cost));
	}

	sort(vec.begin(),vec.end());

	for(int i = 0; i < vec.size(); i++){

		int a = vec[i].from;
		int b = vec[i].to;

		int LCM = lca(a,b);

		//printf("a:%d b:%d LCM:%d\n",a,b,LCM);

		ll value = min_dist[a]+min_dist[b]+vec[i].cost;

		if(depth[a] <= depth[b]){

			swap(a,b);
		}

		while(true){

			if(depth[a] <= depth[LCM])break;

			if(not_COST[a] > value){

				not_COST[a] = value;
			}

			next_node = parent[0][a];
			//next_node = calc_parent[a];
			//calc_parent[a] = LCM;
			a = next_node;
		}

		while(true){

			if(depth[b] <= depth[LCM])break;

			if(not_COST[b] > value){

				not_COST[b] = value;
			}

			next_node = parent[0][b];
			//next_node = calc_parent[b];
			//calc_parent[b] = LCM;
			b = next_node;
		}
	}

	for(int i = 0; i < N; i++){

		not_COST[i] -= min_dist[i];
		//printf("not_COST[%d]:%lld\n",i,not_COST[i]);
	}

	//printf("sum_cost:%lld\n",sum_cost);

	for(int i = 0; i < E; i++){

		rev_G[edge[i].from].push_back(Info(edge[i].to,i));
		rev_G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	ll left = min_dist[start],right = sum_cost,mid = (left+right)/2;
	ll ans = HUGE_NUM;

	//printf("min_dist[start]:%lld\n",min_dist[start]);

	while(left <= right){

		if(is_OK(mid)){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == HUGE_NUM){

		printf("-1\n");
	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 0.5
time_ms: 250
memory_kb: 35664
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005
#define SIZE_V 100005


struct Edge{
	Edge(){

		from = to = 0;
		cost = 0;
	}
	Edge(int arg_from,int arg_to,ll arg_cost){
		from = arg_from;
		to = arg_to;
		cost = arg_cost;
	}
	bool operator<(const struct Edge &arg) const{

		return cost < arg.cost;
	}
	int from,to;
	ll cost;
};

struct Info{
	Info(int arg_to,int arg_edge_index){
		to = arg_to;
		edge_index = arg_edge_index;
	}
	int to,edge_index;
};

struct State{
	State(int arg_node_id,ll arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の昇順(PQ)
	}
	int node_id;
	ll sum_dist;
};

struct Data{
	Data(int arg_pre_node,int arg_pre_edge){
		pre_node = arg_pre_node;
		pre_edge = arg_pre_edge;
	}
	int pre_node,pre_edge;
};


int N,E;
int start,goal;
ll COST[SIZE],not_COST[SIZE];
ll min_dist[SIZE],work_dist[SIZE];
Edge edge[SIZE];

vector<Info> G[SIZE_V],rev_G[SIZE_V];
int root; //根ノードの番号
int MAX_LOG_V = 17;
int POW[18];

int parent[18][SIZE_V],calc_parent[SIZE_V];
int depth[SIZE_V];
vector<Data> D[SIZE_V];
bool is_minPath[SIZE];



//parentとdepthを再帰的に設定
void dfs(int node_id,int parent_id,int d){
	parent[0][node_id] = parent_id;
	depth[node_id] = d;
	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to != parent_id)dfs(G[node_id][i].to,node_id,d+1);
	}
}


void init(){

	dfs(root,-1,0);

	for(int k = 0; k + 1 < MAX_LOG_V; k++){
		for(int node_id = 0; node_id < N; node_id++){
			if(parent[k][node_id] < 0)parent[k+1][node_id] = -1;
			else{
				parent[k+1][node_id] = parent[k][parent[k][node_id]];
			}
		}
	}
}


int lca(int left,int right){

	if(depth[left] > depth[right])swap(left,right);

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(depth[right]-depth[left] >= POW[k]){
			right = parent[k][right];
		}
	}

	if(left == right)return left;

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(parent[k][left] == parent[k][right]){
			//Do nothing
		}else{
			left = parent[k][left];
			right = parent[k][right];
		}
	}
	return parent[0][left];
}

bool is_OK(ll worst_dist){

	for(int i = 0; i < N; i++){

		work_dist[i] = HUGE_NUM;
	}

	priority_queue<State> Q;
	work_dist[start] = 0;

	Q.push(State(start,0));

	int next_node;
	ll next_cost;

	while(!Q.empty()){

		//printf("node_id:%d cost:%lld\n",Q.top().node_id,Q.top().sum_dist);

		if(Q.top().sum_dist > work_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < rev_G[Q.top().node_id].size(); i++){

				next_node = rev_G[Q.top().node_id][i].to;
				if(is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+not_COST[Q.top().node_id] > worst_dist){

					continue;
				}
				if(!is_minPath[rev_G[Q.top().node_id][i].edge_index] && work_dist[Q.top().node_id]+min_dist[Q.top().node_id] > worst_dist){

					continue;
				}

				next_cost = work_dist[Q.top().node_id]+COST[Q.top().node_id];
				if(work_dist[next_node] > next_cost){
					work_dist[next_node] = next_cost;
					Q.push(State(next_node,next_cost));
				}
			}
			Q.pop();
		}
	}

	return work_dist[goal] <= worst_dist;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 18; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d %d %d",&N,&E,&start,&goal);
	start--;
	goal--;

	ll sum_cost = 0;

	for(int i = 0; i < E; i++){

		scanf("%d %d %lld",&edge[i].from,&edge[i].to,&edge[i].cost);
		edge[i].from--;
		edge[i].to--;

		COST[i] = edge[i].cost;
		sum_cost += COST[i];
		G[edge[i].from].push_back(Info(edge[i].to,i));
		G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	for(int i = 0; i < N; i++){

		min_dist[i] = HUGE_NUM;
	}

	min_dist[goal] = 0;
	priority_queue<State> Q;
	Q.push(State(goal,0));

	int next_node;
	ll next_dist;

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){

				next_node = G[Q.top().node_id][i].to;
				next_dist = min_dist[Q.top().node_id]+COST[G[Q.top().node_id][i].edge_index];

				if(min_dist[next_node] > next_dist){

					D[next_node].clear();
					D[next_node].push_back(Data(Q.top().node_id,G[Q.top().node_id][i].edge_index));
					min_dist[next_node] = next_dist;
					Q.push(State(next_node,next_dist));

				}
			}

			Q.pop();
		}
	}
/*
	for(int i = 0; i < N; i++){

		printf("i:%d min_dist:%lld\n",i,min_dist[i]);
	}*/

	//最短経路木を構築
	for(int i = 0; i < N; i++){

		G[i].clear();
	}
	for(int i = 0; i < E; i++){

		is_minPath[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(i == goal)continue;

		for(int k = 0; k < D[i].size(); k++){

			is_minPath[D[i][k].pre_edge] = true;
			G[D[i][k].pre_node].push_back(Info(i,D[i][k].pre_edge)); //goal→start方向
		}
	}

	root = goal;
	init();

	for(int i = 0; i < N; i++){

		calc_parent[i] = parent[0][i];
		not_COST[i] = HUGE_NUM;
	}

	vector<Edge> vec;
	for(int i = 0; i < E; i++){
		if(is_minPath[i])continue;

		vec.push_back(Edge(edge[i].from,edge[i].to,edge[i].cost));
	}

	sort(vec.begin(),vec.end());

	for(int i = 0; i < vec.size(); i++){

		int a = vec[i].from;
		int b = vec[i].to;

		int LCM = lca(a,b);

		//printf("a:%d b:%d LCM:%d\n",a,b,LCM);

		ll value = min_dist[a]+min_dist[b]+vec[i].cost;

		while(true){

			if(depth[a] <= depth[LCM])break;

			if(not_COST[a] > value){

				not_COST[a] = value;
			}

			next_node = calc_parent[a];
			calc_parent[a] = LCM;
			a = next_node;
		}

		while(true){

			if(depth[b] <= depth[LCM])break;

			if(not_COST[b] > value){

				not_COST[b] = value;
			}

			next_node = calc_parent[b];
			calc_parent[b] = LCM;
			b = next_node;
		}
	}

	for(int i = 0; i < N; i++){

		not_COST[i] -= min_dist[i];
		//printf("not_COST[%d]:%lld\n",i,not_COST[i]);
	}

	//printf("sum_cost:%lld\n",sum_cost);

	for(int i = 0; i < E; i++){

		rev_G[edge[i].from].push_back(Info(edge[i].to,i));
		rev_G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	ll left = min_dist[start],right = sum_cost,mid = (left+right)/2;
	ll ans = HUGE_NUM;

	while(left <= right){

		if(is_OK(mid)){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == HUGE_NUM){

		printf("-1\n");
	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 0.19696969696969696
time_ms: 150
memory_kb: 31260
final_rank: 13

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 200005
#define SIZE_V 100005


struct Edge{
	Edge(){

		from = to = 0;
		cost = 0;
	}
	Edge(int arg_from,int arg_to,ll arg_cost){
		from = arg_from;
		to = arg_to;
		cost = arg_cost;
	}
	bool operator<(const struct Edge &arg) const{

		return cost < arg.cost;
	}
	int from,to;
	ll cost;
};

struct Info{
	Info(int arg_to,int arg_edge_index){
		to = arg_to;
		edge_index = arg_edge_index;
	}
	int to,edge_index;
};

struct State{
	State(int arg_node_id,ll arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct State &arg) const{

		return sum_dist > arg.sum_dist; //総距離の昇順(PQ)
	}
	int node_id;
	ll sum_dist;
};

struct Data{
	Data(int arg_pre_node,int arg_pre_edge){
		pre_node = arg_pre_node;
		pre_edge = arg_pre_edge;
	}
	int pre_node,pre_edge;
};


int N,E;
int start,goal;
ll COST[SIZE],not_COST[SIZE];
ll min_dist[SIZE],work_dist[SIZE];
Edge edge[SIZE];

vector<Info> G[SIZE_V],rev_G[SIZE_V];
int root; //根ノードの番号
int MAX_LOG_V = 17;
int POW[18];

int parent[18][SIZE_V],calc_parent[SIZE_V];
int depth[SIZE_V];
vector<Data> D[SIZE_V];
bool is_minPath[SIZE];



//parentとdepthを再帰的に設定
void dfs(int node_id,int parent_id,int d){
	parent[0][node_id] = parent_id;
	depth[node_id] = d;
	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i].to != parent_id)dfs(G[node_id][i].to,node_id,d+1);
	}
}


void init(){

	dfs(root,-1,0);

	for(int k = 0; k + 1 < MAX_LOG_V; k++){
		for(int node_id = 0; node_id < N; node_id++){
			if(parent[k][node_id] < 0)parent[k+1][node_id] = -1;
			else{
				parent[k+1][node_id] = parent[k][parent[k][node_id]];
			}
		}
	}
}


int lca(int left,int right){

	if(depth[left] > depth[right])swap(left,right);

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(depth[right]-depth[left] >= POW[k]){
			right = parent[k][right];
		}
	}

	if(left == right)return left;

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(parent[k][left] == parent[k][right]){
			//Do nothing
		}else{
			left = parent[k][left];
			right = parent[k][right];
		}
	}
	return parent[0][left];
}

bool is_OK(ll worst_dist){

	for(int i = 0; i < N; i++){

		work_dist[i] = HUGE_NUM;
	}

	priority_queue<State> Q;
	work_dist[start] = 0;

	Q.push(State(start,0));

	int next_node;
	ll next_cost;

	while(!Q.empty()){

		//printf("node_id:%d cost:%lld\n",Q.top().node_id,Q.top().sum_dist);

		if(Q.top().sum_dist > work_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < rev_G[Q.top().node_id].size(); i++){

				next_node = rev_G[Q.top().node_id][i].to;
				if(work_dist[Q.top().node_id]+not_COST[Q.top().node_id] > worst_dist){

					continue;
				}
				next_cost = work_dist[Q.top().node_id]+COST[Q.top().node_id];
				if(work_dist[next_node] > next_cost){
					work_dist[next_node] = next_cost;
					Q.push(State(next_node,next_cost));
				}
			}
			Q.pop();
		}
	}

	return work_dist[goal] <= worst_dist;
}

int main(){

	POW[0] = 1;
	for(int i = 1; i < 18; i++){

		POW[i] = POW[i-1]*2;
	}

	scanf("%d %d %d %d",&N,&E,&start,&goal);
	start--;
	goal--;

	ll sum_cost = 0;

	for(int i = 0; i < E; i++){

		scanf("%d %d %lld",&edge[i].from,&edge[i].to,&edge[i].cost);
		edge[i].from--;
		edge[i].to--;

		COST[i] = edge[i].cost;
		sum_cost += COST[i];
		G[edge[i].from].push_back(Info(edge[i].to,i));
		G[edge[i].to].push_back(Info(edge[i].from,i));
	}

	for(int i = 0; i < N; i++){

		min_dist[i] = HUGE_NUM;
	}

	min_dist[goal] = 0;
	priority_queue<State> Q;
	Q.push(State(goal,0));

	int next_node;
	ll next_dist;

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().node_id]){

			Q.pop();

		}else{

			for(int i = 0; i < G[Q.top().node_id].size(); i++){

				next_node = G[Q.top().node_id][i].to;
				next_dist = min_dist[Q.top().node_id]+COST[G[Q.top().node_id][i].edge_index];

				if(min_dist[next_node] > next_dist){

					D[next_node].clear();
					D[next_node].push_back(Data(Q.top().node_id,G[Q.top().node_id][i].edge_index));
					min_dist[next_node] = next_dist;
					Q.push(State(next_node,next_dist));

				}
			}

			Q.pop();
		}
	}
/*
	for(int i = 0; i < N; i++){

		printf("i:%d min_dist:%lld\n",i,min_dist[i]);
	}*/

	//最短経路木を構築
	for(int i = 0; i < N; i++){

		G[i].clear();
	}
	for(int i = 0; i < E; i++){

		is_minPath[i] = false;
	}

	for(int i = 0; i < N; i++){
		if(i == goal)continue;

		for(int k = 0; k < D[i].size(); k++){

			is_minPath[D[i][k].pre_edge] = true;
			G[D[i][k].pre_node].push_back(Info(i,D[i][k].pre_edge)); //goal→start方向
			//printf("%d-%dに張る\n",D[i][k].pre_node,i);
			rev_G[i].push_back(Info(D[i][k].pre_node,D[i][k].pre_edge)); //start→goal方向
		}
	}

	root = goal;
	init();

	for(int i = 0; i < N; i++){

		calc_parent[i] = parent[0][i];
		not_COST[i] = HUGE_NUM;
	}

	vector<Edge> vec;
	for(int i = 0; i < E; i++){
		if(is_minPath[i])continue;

		vec.push_back(Edge(edge[i].from,edge[i].to,edge[i].cost));
	}

	sort(vec.begin(),vec.end());

	for(int i = 0; i < vec.size(); i++){

		int a = vec[i].from;
		int b = vec[i].to;

		int LCM = lca(a,b);

		//printf("a:%d b:%d LCM:%d\n",a,b,LCM);

		ll value = min_dist[a]+min_dist[b]+vec[i].cost;

		while(true){

			if(depth[a] <= depth[LCM])break;

			if(not_COST[a] > value){

				not_COST[a] = value;
			}

			next_node = calc_parent[a];
			calc_parent[a] = LCM;
			a = next_node;
		}

		while(true){

			if(depth[b] <= depth[LCM])break;

			if(not_COST[b] > value){

				not_COST[b] = value;
			}

			next_node = calc_parent[b];
			calc_parent[b] = LCM;
			b = next_node;
		}
	}

	for(int i = 0; i < N; i++){

		not_COST[i] -= min_dist[i];
		//printf("not_COST[%d]:%lld\n",i,not_COST[i]);
	}

	//printf("sum_cost:%lld\n",sum_cost);

	ll left = min_dist[start],right = sum_cost,mid = (left+right)/2;
	ll ans = HUGE_NUM;

	while(left <= right){

		if(is_OK(mid)){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == HUGE_NUM){

		printf("-1\n");
	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 0.19696969696969696
time_ms: 50
memory_kb: 30616
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
typedef pair<ll, P> P3;
typedef pair<P ,P> PP;
constexpr ll MOD = ll(1e9) + 7;
constexpr int IINF = INT_MAX;
constexpr ll LLINF = LLONG_MAX;
constexpr int MAX_N = int(1e5) + 5;
constexpr double EPS = 1e-9;
constexpr int di[] = {0, 1, 0, -1}, dj[] = {1, 0, -1, 0};
#define REP(i, n) for (int i = 0; i < n; i++)
#define REPR(i, n) for (int i = n; i > 0; i--)
#define SORT(v) sort((v).begin(), (v).end())
#define SORTR(v) sort((v).rbegin(), (v).rend())
#define ALL(v) (v).begin(), (v).end()

int N, M, S, T;
vector<vector<P> > g;

vector<vector<P> > dijkstra(int start){
    vector<vector<P> > dmin(2);  // 最短距離と2番目の最短距離
    for(int i=0;i<2;i++){
        dmin[i].assign(N, {LLINF/4, -1});
    }
    priority_queue<P3, vector<P3>, greater<P3> > que;  // {距離,{現在の頂点,直前の頂点}}
    dmin[0][start] = {0, -1};
    que.push({0,{start, -1}});
    while(!que.empty()){
        P3 p = que.top();
        que.pop();
        ll u = p.second.first, pre = p.second.second;
        if(p.first > dmin[1][u].first) continue;
        for(auto e : g[u]){
            ll v = e.first, c = e.second;
            if(dmin[0][v].first > p.first + c){
                dmin[1][v] = dmin[0][v];
                dmin[0][v] = {p.first + c, u};
                que.push({dmin[0][v].first, {v, u}});
            }
            else if(dmin[1][v].first > p.first + c && dmin[0][v].second != u && v != pre){  // Uターンは禁止する
                dmin[1][v] = {p.first + c, u};
                que.push({dmin[1][v].first, {v, u}});
            }
        }
    }
    return dmin;
}

int main() {
    cin >> N >> M >> S >> T;
    S--; T--;
    g.resize(N);
    for(int i=0;i<M;i++){
        ll u, v, c;
        cin >> u >> v >> c;
        u--; v--;
        g[u].push_back({v, c});
        g[v].push_back({u, c});
    }
    vector<vector<P> > smin, tmin;
    smin = dijkstra(S);
    tmin = dijkstra(T);
    ll ans = 0, L = smin[0][T].first;
    for(int i=0;i<N;i++){
        if(i == T)continue;
        if(smin[0][i].first + tmin[0][i].first == L){  // 最短経路上の頂点か
            ans = max(ans, smin[0][i].first + tmin[1][i].first);  // 最短経路で頂点iに行き、迂回路でTまで行く
        }
    }
    cout << (ans < LLINF/4 ? ans : -1) << endl;
    return 0;
}
accuracy: 0.19696969696969696
time_ms: 90
memory_kb: 15092
final_rank: 11

code_snippet: #include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

#define maxn 100010
#define maxm 800010
typedef long long ll;
struct Edge {
	Edge *next;
	int to, w;
} *last[maxn], e[maxm], *ecnt = e;
inline void link(int a, int b, int w)
{
	*++ecnt = (Edge) {last[a], b, w}; last[a] = ecnt;
	*++ecnt = (Edge) {last[b], a, w}; last[b] = ecnt;
}
ll d[maxn];
int fa[maxn];
int n, m, s, t;
ll f[maxn];
struct Node *null;
struct Node {
	Node *ch[2];
	ll val, tag;
	int lca;
	inline void set_tag(ll tg)
	{
		val += tg;
		tag += tg;
	}
	inline void pushdown()
	{
		if (tag)
		{
			if (ch[0] != null) ch[0] -> set_tag(tag);
			if (ch[1] != null) ch[1] -> set_tag(tag);
			tag = 0;
		}
	}
} *root[maxn], mem[maxm], *tot = mem;
Node *merge(Node *a, Node *b)
{
	if (a == mem) return b;
	if (b == mem) return a;
	if (a -> val > b -> val) std::swap(a, b);
	a -> pushdown();
	std::swap(a -> ch[0], a -> ch[1]);
	a -> ch[1] = merge(a -> ch[1], b);
	return a;
}
int son[maxn], size[maxn], top[maxn], dep[maxn], inv[maxn], dfn[maxn], timer;
void dfs1(int x)
{
	size[x] = 1; dep[x] = dep[fa[x]] + 1;
	for (Edge *iter = last[x]; iter; iter = iter -> next)
		if (fa[iter -> to] == x)
		{
			dfs1(iter -> to);
			size[x] += size[iter -> to];
			size[iter -> to] > size[son[x]] ? son[x] = iter -> to : 0;
		}
}
void dfs2(int x)
{
	top[x] = son[fa[x]] == x ? top[fa[x]] : x;
	dfn[x] = ++timer;
	for (Edge *iter = last[x]; iter; iter = iter -> next)
		if (fa[iter -> to] == x) dfs2(iter -> to);
	inv[x] = timer;
}
inline int getlca(int a, int b)
{
	while (top[a] != top[b])
		dep[top[a]] < dep[top[b]]
			? b = fa[top[b]]
			: a = fa[top[a]];
	return dep[a] < dep[b] ? a : b;
}
void dfs(int x)
{
	root[x] = mem;
	for (Edge *iter = last[x]; iter; iter = iter -> next)
		if (fa[iter -> to] == x)
		{
			dfs(iter -> to);
			if (root[iter -> to] != null) root[iter -> to] -> set_tag(iter -> w);
			root[x] = merge(root[x], root[iter -> to]);
		}
		else if (iter -> to != fa[x])
		{
			*++tot = (Node) {{mem, mem}, d[iter -> to] + iter -> w, 0, getlca(x, iter -> to)};
			root[x] = merge(root[x], tot);
		}
	while (root[x] != null && dfn[x] <= dfn[root[x] -> lca] && dfn[root[x] -> lca] <= inv[x])
		root[x] = merge(root[x] -> ch[0], root[x] -> ch[1]);
	f[x] = root[x] -> val;
}
struct Queue {
	ll d; int x;
	inline bool operator < (const Queue &that) const {return d > that.d;}
} ;
std::priority_queue<Queue> q;
inline bool check(ll mid)
{
	 memset(d, 63, sizeof (d));
	 const ll inf = d[0];
	 q.push((Queue) {d[s] = 0, s});
	 while (!q.empty())
	 {
	 	Queue now = q.top(); q.pop();
	 	if (now.d != d[now.x]) continue;
	 	int x = now.x;
	 	if (d[x] + f[x] > mid) continue;
	 	for (Edge *iter = last[x]; iter; iter = iter -> next)
	 		if (d[iter -> to] > d[x] + iter -> w)
	 		{
	 			d[iter -> to] = d[x] + iter -> w;
	 			q.push((Queue) {d[iter -> to], iter -> to});
	 		}
	 }
	 return d[t] != inf;
}
int main()
{
	null = mem; mem -> val = ~0ULL >> 3; mem -> ch[0] = mem -> ch[1] = mem;
	scanf("%d%d%d%d", &n, &m, &s, &t);
	for (int i = 1; i <= m; ++i)
	{
		int a, b, w; scanf("%d%d%d", &a, &b, &w);
		link(a, b, w);
	}
	memset(d, 63, sizeof (d));
	q.push((Queue) {d[t] = 0, t});
	while (!q.empty())
	{
		Queue now = q.top(); q.pop();
		if (now.d != d[now.x]) continue;
		int x = now.x;
		for (Edge *iter = last[x]; iter; iter = iter -> next)
			if (d[iter -> to] > d[x] + iter -> w)
			{
				d[iter -> to] = d[x] + iter -> w;
				q.push((Queue) {d[iter -> to], iter -> to});
			}
	}

	for (int i = 1; i <= n; ++i)
		for (Edge *iter = last[i]; iter; iter = iter -> next)
			if (d[iter -> to] == d[i] + iter -> w)
				fa[iter -> to] = i;

	dfs1(t);
	dfs2(t);
	dfs(t);
//	for (int i = 1; i <= n; ++i) printf("%lld\n", f[i]);
	ll left = 0, right = 1e18;
	while (left < right)
	{
		ll mid = left + right >> 1;
		if (check(mid)) right = mid;
		else left = mid + 1;
	}
	printf("%lld\n", left > 1e17 ? -1 : left);
	return 0;
}
accuracy: 1
time_ms: 700
memory_kb: 22816
final_rank: 3