Problem:
定期券(Commuter Pass)
JOI 君が住む都市には
N
個の駅があり，それぞれ
1, 2, ..., N
の番号が付けられている．また，
M
本の鉄道路線があり，それぞれ
1, 2, ..., M
の番号が付けられている．鉄道路線
i
(
1 \leq i \leq M
) は駅
A_i
と駅
B_i
を双方向に結んでおり，乗車運賃は
C_i
円である．
JOI 君は駅S の近くに住んでおり，駅
T
の近くのIOI 高校に通っている．そのため，両者を結ぶ定期券を購入することにした．定期券を購入する際には，駅
S
と駅
T
の間を最小の運賃で移動する経路を一つ指定しなければならない．この定期券を用いると，指定した経路に含まれる鉄道路線は双方向に自由に乗り降りできる．
JOI 君は，駅
U
および駅
V
の近くにある書店もよく利用している．そこで，駅
U
から駅
V
への移動にかかる運賃ができるだけ小さくなるように定期券を購入したいと考えた．
駅
U
から駅
V
への移動の際は，まず駅
U
から駅
V
への経路を1 つ選ぶ．この経路に含まれる鉄道路線
i
において支払うべき運賃は，
鉄道路線
i
が定期券を購入する際に指定した経路に含まれる場合，0 円
鉄道路線
i
が定期券を購入する際に指定した経路に含まれない場合，
C_i
円
となる．この運賃の合計が，駅
U
から駅
V
への移動にかかる運賃である．
定期券を購入する際に指定する経路をうまく選んだときの，駅
U
から駅
V
への移動にかかる運賃の最小値を求めたい．
課題
定期券を購入する際に指定する経路をうまく選んだときの，駅
U
から駅
V
への移動にかかる運賃の最小値を求めるプログラムを作成せよ．
入力
標準入力から以下の入力を読み込め．
1 行目には，2 個の整数
N, M
が書かれている．これらは，JOI 君が住む都市に
N
個の駅と
M
本の鉄道路線があることを表す．
2 行目には，2 個の整数
S, T
が書かれている．これらは，JOI 君が駅
S
から駅
T
への定期券を購入することを表す．
3 行目には，2 個の整数
U, V
が書かれている．これらは，JOI 君が駅
U
から駅
V
への移動にかかる運賃を最小化したいことを表す．
続く
M
行のうちの
i
行目(
1 \leq i \leq M
) には，3 個の整数
A_i, B_i,C_i
が書かれている．これらは，鉄道路線
i
が駅
A_i
と駅
B_i
を双方向に結び，その運賃が
C_i
円であることを表す．
出力
標準出力に，定期券を購入する際に駅
S
から駅
T
への経路をうまく指定したときの，駅
U
から駅
V
への移動にかかる運賃の最小値を1 行で出力せよ．
制限
すべての入力データは以下の条件を満たす．
2 \leq N \leq 100 000．
1 \leq M \leq 200 000．
1 \leq S \leq N．
1 \leq T \leq N．
1 \leq U \leq N．
1 \leq V \leq N．
S ≠ T．
U ≠ V．
S ≠ U
または
T ≠ V．
どの駅から他のどの駅へも1 本以上の鉄道路線を用いて到達できる．
1 \leq A_i < B_i \leq N (1 \leq i l\leq M)．
1 \leq i < j \leq M
に対し，
A_i ≠ A_j
または
B_i ≠ B_j．
1 \leq C_i \leq 1 000 000 000 (1 \leq i \leq M)．
入出力例
入力例1
6 6
1 6
1 4
1 2 1
2 3 1
3 5 1
2 4 3
4 5 2
5 6 1
出力例1
2
この入力例では，定期券を買う際に指定できる経路は駅1 → 駅2 → 駅3 → 駅5 → 駅6 という経路に限られる．
駅1 から駅4 への移動にかかる運賃を最小化するには，駅1 → 駅2 → 駅3 → 駅5 → 駅4 という経路を選べばよい．この経路を選んだ場合，各鉄道路線において支払うべき運賃は，
駅4 と駅5 を結ぶ鉄道路線5 においては，2 円．
それ以外の鉄道路線においては，0 円．
となるので，かかる運賃の合計は2 円となる．
入力例2
6 5
1 2
3 6
1 2 1000000000
2 3 1000000000
3 4 1000000000
4 5 1000000000
5 6 1000000000
出力例2
3000000000
この入力例では，駅3 から駅6 への移動に定期券を用いない．
入力例3
8 8
5 7
6 8
1 2 2
2 3 3
3 4 4
1 4 1
1 5 5
2 6 6
3 7 7
4 8 8
出力例3
15
入力例4
5 5
1 5
2 3
1 2 1
2 3 10
2 4 10
3 5 10
4 5 10
出力例4
0
入力例5
10 15
6 8
7 9
2 7 12
8 10 17
1 3 1
3 8 14
5 7 15
2 3 7
1 10 14
3 6 12
1 5 10
8 9 1
2 9 7
1 4 1
1 8 1
2 4 7
5 6 16
出力例5
19
情報オリンピック日本委員会作 『第17 回日本情報オリンピック(JOI 2017/2018) 本選』

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < int(n); ++ (i))
#define ALL(x) begin(x), end(x)
using ll = long long;
using namespace std;
template <class T> inline void chmin(T & a, T const & b) { a = min(a, b); }

vector<ll> dijkstra(vector<vector<pair<int, ll> > > const & g, int root) {
    vector<ll> dist(g.size(), LLONG_MAX);
    priority_queue<pair<ll, int> > que;
    dist[root] = 0;
    que.emplace(- dist[root], root);
    while (not que.empty()) {
        ll dist_i; int i; tie(dist_i, i) = que.top(); que.pop();
        if (dist[i] < - dist_i) continue;
        for (auto it : g[i]) {
            int j; ll cost; tie(j, cost) = it;
            if (- dist_i + cost < dist[j]) {
                dist[j] = - dist_i + cost;
                que.emplace(dist_i - cost, j);
            }
        }
    }
    return dist;
}

int main() {
    // input
    int n, m; cin >> n >> m;
    int s, t; cin >> s >> t; -- s; -- t;
    int u, v; cin >> u >> v; -- u; -- v;
    vector<vector<pair<int, ll> > > g(n);
    REP (i, m) {
        int a, b; ll c; cin >> a >> b >> c; -- a; -- b;
        g[a].emplace_back(b, c);
        g[b].emplace_back(a, c);
    }

    // solve
    vector<ll> dist_s = dijkstra(g, s);
    vector<ll> dist_t = dijkstra(g, t);
    vector<ll> dist_u = dijkstra(g, u);
    vector<ll> dist_v = dijkstra(g, v);
    vector<int> order(n);
    iota(ALL(order), 0);
    sort(ALL(order), [&](int i, int j) { return dist_s[i] < dist_s[j]; });
    vector<ll> from_u(n, LLONG_MAX);
    vector<ll> from_v(n, LLONG_MAX);
    ll answer = dist_u[v];
    for (int i : order) {
        if (dist_s[i] + dist_t[i] == dist_s[t]) {  // on a shortest path
            chmin(from_u[i], dist_u[i]);
            chmin(from_v[i], dist_v[i]);
            for (auto edge : g[i]) {
                int j; ll cost; tie(j, cost) = edge;
                if (dist_s[j] + cost == dist_s[i]) {  // if a parent
                    chmin(from_u[i], from_u[j]);
                    chmin(from_v[i], from_v[j]);
                }
            }
            chmin(answer, from_u[i] + dist_v[i]);
            chmin(answer, from_v[i] + dist_u[i]);
        }
    }

    // output
    cout << answer << endl;
    return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 22908
final_rank: 5

code_snippet: #include <bits/stdc++.h>




namespace zawa {

using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;

using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;

using usize = std::size_t;

} // namespace zawa


namespace zawa {

void SetFastIO() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
}

void SetPrecision(u32 dig) {
    std::cout << std::fixed << std::setprecision(dig);
}

} // namespace zawa



namespace zawa {

class DisjointSetUnion {
public:
    DisjointSetUnion() = default;

    DisjointSetUnion(usize n) : n_{n}, data_(n, -1) {
        data_.shrink_to_fit();
    }
    
    u32 leader(u32 v) {
        return data_[v] < 0 ? v : static_cast<u32>(data_[v] = leader(data_[v]));
    }

    bool same(u32 u, u32 v) {
        return leader(u) == leader(v);
    }

    bool merge(u32 u, u32 v) {
        assert(u < n_);
        assert(v < n_);
        u = leader(u);
        v = leader(v);
        if (u == v) return false;
        if (data_[u] > data_[v]) std::swap(u, v);
        data_[u] += data_[v];
        data_[v] = u;
        return true;
    }

    inline usize size() const noexcept {
        return n_;
    }

    usize size(u32 v) {
        assert(v < n_);
        return static_cast<usize>(-data_[leader(v)]);
    }

    std::vector<std::vector<u32>> enumerate() {
        std::vector<std::vector<u32>> res(n_);
        for (u32 v{} ; v < n_ ; v++) {
            res[leader(v)].push_back(v);
        }
        res.erase(std::remove_if(res.begin(), res.end(),
                    [](const auto& arr) -> bool { return arr.empty(); }), res.end());
        return res;
    }

private:
    usize n_{};
    std::vector<i32> data_;
};

} // namespace zawa
using namespace zawa;

const long long INF{(long long)2e18};
std::vector<long long> dij(const std::vector<std::vector<std::pair<int, int>>>& g, int s) {
    assert(0 <= s and s < (int)g.size());
    std::vector<long long> res(g.size(), INF);
    using qt = std::pair<long long, int>;
    std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
    res[s] = 0;
    que.push(std::pair{res[s], s});
    while (que.size()) {
        auto [d, v]{que.top()};
        que.pop();
        if (res[v] < d) continue;
        for (auto [x, w] : g[v]) if (res[x] > d + w) {
            res[x] = d + w;
            que.push(std::pair{res[x], x});
        }
    }
    return res;
}

int main() {
    SetFastIO();

    int N, M;
    std::cin >> N >> M;
    int S, T, U, V;
    std::cin >> S >> T >> U >> V;
    S--; T--; U--; V--;
    std::vector<int> A(M), B(M), C(M);
    std::vector<std::vector<std::pair<int, int>>> g(N);
    for (int i{} ; i < M ; i++) {
        std::cin >> A[i] >> B[i] >> C[i];
        A[i]--; B[i]--;
        g[A[i]].push_back(std::pair{ B[i], C[i] });
        g[B[i]].push_back(std::pair{ A[i], C[i] });
    }
    auto ST{dij(g, S)};
    std::vector<bool> ok(M);
    {
        std::vector<std::vector<std::pair<int, int>>> dag(N);
        for (int i{} ; i < M ; i++) {
            if (ST[A[i]] + C[i] == ST[B[i]]) {
                dag[B[i]].push_back(std::pair{ A[i], i });
            }
            if (ST[B[i]] + C[i] == ST[A[i]]) {
                dag[A[i]].push_back(std::pair{ B[i], i });
            }
        }
        std::vector<bool> vis(N);
        vis[T] = true;
        std::queue<int> que;
        que.push(T);
        while (que.size()) {
            int v{que.front()};
            que.pop();
            for (auto [x, i] : dag[v]) {
                ok[i] = true;
                if (!vis[x]) {
                    vis[x] = true;
                    que.push(x);
                }
            }
        }
    }
    //[N, 2N) -> S->T側
    //[2N, 3N) -> T->S側
    std::vector<std::vector<std::pair<int, int>>> g2(4 * N);
    for (int i{} ; i < N ; i++) {
        g2[i].push_back(std::pair{N + i, 0});
        g2[i].push_back(std::pair{N + N + i, 0});
        g2[N + i].push_back(std::pair{N + N + N + i, 0});
        g2[N + N + i].push_back(std::pair{N + N + N + i, 0});
    }
    for (int i{} ; i < M ; i++) {
        g2[A[i]].push_back(std::pair{B[i], C[i]});
        g2[B[i]].push_back(std::pair{A[i], C[i]});
        if (ok[i] and ST[A[i]] + C[i] == ST[B[i]]) {
            g2[N + A[i]].push_back(std::pair{N + B[i], 0});
            g2[N + N + B[i]].push_back(std::pair{N + N + A[i], 0});
        }
        if (ok[i] and ST[B[i]] + C[i] == ST[A[i]]) {
            g2[N + B[i]].push_back(std::pair{N + A[i], 0});
            g2[N + N + A[i]].push_back(std::pair{N + N + B[i], 0});
        }
        g2[N + N + N + A[i]].push_back(std::pair{N + N + N + B[i], C[i]});
        g2[N + N + N + B[i]].push_back(std::pair{N + N + N + A[i], C[i]});
    }
    auto UV{dij(g2, U)};
    std::cout << UV[N + N + N + V] << '\n';
}
accuracy: 1
time_ms: 280
memory_kb: 57244
final_rank: 16

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <climits>
using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
#define HUGE_NUM 99999999999999999
#define NUM 100001

enum Type {
    from_S,
    from_T,
    from_U,
    from_V,
};

struct Edge {
    int to;
    ll cost;
    Edge(int arg_to, ll arg_cost) : to(arg_to), cost(arg_cost) {}
};

struct Info {
    int node_id;
    ll sum_cost;
    Info(int arg_node_id, ll arg_sum_cost) : node_id(arg_node_id), sum_cost(arg_sum_cost) {}
    bool operator<(const Info &arg) const {
        return sum_cost > arg.sum_cost;
    }
};

struct Data {
    int node_id;
    ll dist;
    Data(int arg_node_id, ll arg_dist) : node_id(arg_node_id), dist(arg_dist) {}
    bool operator<(const Data &arg) const {
        return dist < arg.dist;
    }
};

int N, M, S, T, U, V;
int start[4];
vector<Edge> G[NUM];
ll min_dist[NUM][4], min_dist_from_U[NUM];

void calc(Type type) {
    for (int i = 1; i <= N; i++) {
        min_dist[i][type] = HUGE_NUM;
    }
    min_dist[start[type]][type] = 0;

    priority_queue<Info> Q;
    Q.emplace(start[type], 0);

    while (!Q.empty()) {
        int current_node = Q.top().node_id;
        ll current_cost = Q.top().sum_cost;
        Q.pop();

        if (current_cost > min_dist[current_node][type]) continue;

        for (const auto &edge : G[current_node]) {
            int next_node = edge.to;
            ll next_cost = current_cost + edge.cost;

            if (min_dist[next_node][type] > next_cost) {
                min_dist[next_node][type] = next_cost;
                Q.emplace(next_node, next_cost);
            }
        }
    }
}

int main() {
    cin >> N >> M;
    cin >> S >> T;
    cin >> U >> V;

    start[from_S] = S;
    start[from_T] = T;
    start[from_U] = U;
    start[from_V] = V;

    for (int loop = 0; loop < M; loop++) {
        int from, to;
        ll cost;
        cin >> from >> to >> cost;
        G[from].emplace_back(to, cost);
        G[to].emplace_back(from, cost);
    }

    calc(from_S);
    calc(from_T);
    calc(from_U);
    calc(from_V);

    vector<Data> DATA;
    for (int i = 1; i <= N; i++) {
        DATA.emplace_back(i, min_dist[i][from_S]);
    }
    sort(DATA.begin(), DATA.end());

    ll ans = min_dist[V][from_U];
    for (int i = 1; i <= N; i++) {
        min_dist_from_U[i] = min_dist[i][from_U];
    }

    for (const auto &data : DATA) {
        int node_id = data.node_id;
        ans = min(ans, min_dist[node_id][from_U] + min_dist[node_id][from_V]);
        for (const auto &edge : G[node_id]) {
            int adj_node = edge.to;
            if (min_dist[node_id][from_S] + edge.cost + min_dist[adj_node][from_T] != min_dist[T][from_S]) continue;
            min_dist[adj_node][from_U] = min(min_dist[adj_node][from_U], min_dist[node_id][from_U]);
        }
    }

    for (const auto &data : DATA) {
        int node_id = data.node_id;
        ans = min(ans, min_dist[node_id][from_V] + min_dist_from_U[node_id]);
        for (const auto &edge : G[node_id]) {
            int adj_node = edge.to;
            if (min_dist[node_id][from_S] + edge.cost + min_dist[adj_node][from_T] != min_dist[T][from_S]) continue;
            min_dist[adj_node][from_V] = min(min_dist[adj_node][from_V], min_dist[node_id][from_V]);
        }
    }

    cout << ans << endl;

    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 23688
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, int> pll;
ll INF = 1LL<<60;
int n, m, s, t, u, v;
ll a, b, c, sd[100010], ud[100010], vd[100010];
vector<pll> edge[100010];
priority_queue<pll, vector<pll>, greater<pll> > pq;

void dij(int now, ll *dist){
    for(int i=0;i<=n;i++) dist[i] = INF;
    dist[now] = 0;
    pq.push(pll(0, now));
    while(!pq.empty()){
        pll p = pq.top();
        pq.pop();
        for(int i=0;i<edge[p.second].size();i++){
            ll cst = p.first + edge[p.second][i].first;
            int nxt = edge[p.second][i].second;
            if(dist[nxt] > cst){
                dist[nxt] = cst;
                pq.push(pll(cst, nxt));
            }
        }
    }
}

vector<pll> vec;
ll dp[100010][5];

int main(){
    
    cin >> n >> m >> s >> t >> u >> v;
    for(int i=0;i<m;i++){
        cin >> a >> b >> c;
        edge[a].push_back(pll(c, b));
        edge[b].push_back(pll(c, a));
    }
    
    dij(s, sd);
    dij(u, ud);
    dij(v, vd);
    
    for(int i=1;i<=n;i++) vec.push_back(pll(sd[i], i));
    sort(vec.begin(), vec.end());
    
    for(int i=0;i<=n;i++){
        for(int j=0;j<5;j++) dp[i][j] = INF;
    }
    dp[s][0] = ud[s];
    dp[s][1] = vd[s];
    dp[s][2] = ud[s] + vd[s];
    
    for(int i=0;i<vec.size();i++){
        int now = vec[i].second;
        for(int j=0;j<edge[now].size();j++){
            int pre = edge[now][j].second;
            if(sd[now] != sd[pre]+edge[now][j].first) continue;
            dp[now][0] = min(dp[now][0], min(dp[pre][0], ud[now]));
            dp[now][1] = min(dp[now][1], min(dp[pre][1], vd[now]));
            dp[now][2] = min(dp[now][2], min(dp[pre][2], ud[now]+vd[now]));
            dp[now][2] = min(dp[now][2], min(ud[now]+dp[pre][1], dp[pre][0]+vd[now]));
        }
    }
    
    cout << min(dp[t][2], ud[v]) << endl;
    
    return(0);
}
accuracy: 1
time_ms: 270
memory_kb: 24532
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
ll INF = 1LL<<60;
int n, m, s, t, u, v;
ll a, b, c, sd[100010], ud[100010], vd[100010];
vector<pll> edge[100010];

void dij(int now, ll *dist){
    for(int i=0;i<=n;i++) dist[i] = INF;
    dist[now] = 0;
    priority_queue<pll, vector<pll>, greater<pll> > pq;
    pq.push(pll(0, now));
    while(!pq.empty()){
        pll p = pq.top();
        pq.pop();
        for(int i=0;i<edge[p.second].size();i++){
            ll cst = p.first + edge[p.second][i].first;
            int nxt = edge[p.second][i].second;
            if(dist[nxt] > cst){
                dist[nxt] = cst;
                pq.push(pll(cst, nxt));
            }
        }
    }
}

vector<pll> vec;
ll dp[100010][5];

int main(){
    
    cin >> n >> m >> s >> t >> u >> v;
    for(int i=0;i<m;i++){
        cin >> a >> b >> c;
        edge[a].push_back(pll(c, b));
        edge[b].push_back(pll(c, a));
    }
    
    dij(s, sd);
    dij(u, ud);
    dij(v, vd);
    
    for(int i=1;i<=n;i++) vec.push_back(pll(sd[i], i));
    sort(vec.begin(), vec.end());
    
    for(int i=0;i<=n;i++){
        for(int j=0;j<5;j++) dp[i][j] = INF;
    }
    dp[s][1] = ud[s];
    dp[s][2] = vd[s];
    dp[s][3] = ud[s] + vd[s];
    
    for(int i=0;i<vec.size();i++){
        int now = vec[i].second;
        for(int j=0;j<edge[now].size();j++){
            int pre = edge[now][j].second;
            if(sd[now] != sd[pre]+edge[now][j].first) continue;
            dp[now][1] = min(dp[now][1], min(dp[pre][1], ud[now]));
            dp[now][2] = min(dp[now][2], min(dp[pre][2], vd[now]));
            dp[now][3] = min(dp[now][3], dp[pre][3]);
            dp[now][3] = min(dp[now][3], dp[pre][1]+vd[now]);
            dp[now][3] = min(dp[now][3], ud[now]+dp[pre][2]);
            dp[now][3] = min(dp[now][3], ud[now]+vd[now]);
        }
    }
    
    cout << min(dp[t][3], ud[v]) << endl;
    
    return(0);
}
accuracy: 1
time_ms: 270
memory_kb: 25444
final_rank: 10

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, int> pll;
ll INF = 1e18;
int n, m, s, t, u, v;
ll a, b, c, dist[3][100010];
vector<pll> edge[100010];
priority_queue<pll, vector<pll>, greater<pll> > pq;

void dij(int now, int num){
    for(int i=0;i<=n;i++) dist[num][i] = INF;
    dist[num][now] = 0;
    pq.push(pll(0, now));
    while(!pq.empty()){
        pll p = pq.top();
        pq.pop();
        for(int i=0;i<edge[p.second].size();i++){
            ll cst = p.first + edge[p.second][i].first;
            int nxt = edge[p.second][i].second;
            if(dist[num][nxt] > cst){
                dist[num][nxt] = cst;
                pq.push(pll(cst, nxt));
            }
        }
    }
}

vector<pll> vec;
ll dp[100010][3];

int main(){
    
    cin >> n >> m >> s >> t >> u >> v;
    for(int i=0;i<m;i++){
        cin >> a >> b >> c;
        edge[a].push_back(pll(c, b));
        edge[b].push_back(pll(c, a));
    }
    
    dij(s, 0);
    dij(u, 1);
    dij(v, 2);
    
    for(int i=1;i<=n;i++) vec.push_back(pll(dist[0][i], i));
    sort(vec.begin(), vec.end());
    
    for(int i=0;i<=n;i++){
        for(int j=0;j<3;j++) dp[i][j] = INF;
    }
    dp[s][0] = dist[1][s];
    dp[s][1] = dist[2][s];
    dp[s][2] = dist[1][s] + dist[2][s];
    
    for(int i=0;i<vec.size();i++){
        int now = vec[i].second;
        for(int j=0;j<edge[now].size();j++){
            int pre = edge[now][j].second;
            if(dist[0][now] != dist[0][pre]+edge[now][j].first) continue;
            dp[now][0] = min(dp[now][0], min(dp[pre][0], dist[1][now]));
            dp[now][1] = min(dp[now][1], min(dp[pre][1], dist[2][now]));
            dp[now][2] = min(dp[now][2], min(dp[pre][2], dist[1][now]+dist[2][now]));
            dp[now][2] = min(dp[now][2], dist[1][now]+dp[pre][1]);
            dp[now][2] = min(dp[now][2], dp[pre][0]+dist[2][now]);
        }
    }
    
    cout << min(dp[t][2], dist[1][v]) << endl;
    
    return(0);
}
accuracy: 1
time_ms: 270
memory_kb: 22908
final_rank: 8

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    int S, T, U, V;
    cin >> S >> T >> U >> V;
    S -= 1, T -= 1, U -= 1, V -= 1;
    vector<vector<pair<int, ll>>> g(n);
    for (int i = 0; i < m; i++) {
        int x, y, z;
        cin >> x >> y >> z;
        x -= 1, y -= 1;
        g[x].push_back({y, z});
        g[y].push_back({x, z});
    }
    using P = pair<ll, int>;
    priority_queue<P, vector<P>, greater<P>> pq;
    auto dik = [&](int x) -> vector<ll> {
        vector<ll> d(n, 1e18);
        d[x] = 0;
        pq.push({0, x});
        while (pq.size()) {
            auto p = pq.top();
            pq.pop();
            int s = p.second;
            if (d[s] != p.first) continue;
            for (auto to : g[s]) {
                ll cost = p.first + to.second;
                int t = to.first;
                if (d[t] > cost) {
                    d[t] = cost;
                    pq.push({cost, t});
                }
            }
        }
        return d;
    };
    vector<ll> fs = dik(S), ft = dik(T), fv = dik(V), fu = dik(U);
    ll res = fv[U];
    vector<int> idx(n);
    iota(idx.begin(), idx.end(), 0);
    sort(idx.begin(), idx.end(), [&](auto i, auto j) { return fs[i] < fs[j]; });
    for (int _ = 0; _ < 2; _++) {
        swap(U, V);
        swap(fu, fv);
        vector<ll> dp(n, 1e18);
        for (int i : idx) {
            if (fs[i] + ft[i] != fs[T]) continue;
            dp[i] = min(dp[i], fu[i]);
            res = min(res, dp[i] + fv[i]);
            for (auto to : g[i]) {
                dp[to.first] = min(dp[to.first], dp[i]);
            }
        }
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 160
memory_kb: 21240
final_rank: 2

code_snippet: #include<iostream>
#include<algorithm>    
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<ctime>
#include<fstream>
#include<functional>
#include<map>
#include<math.h>
#include<numeric>
#include<queue>
#include<set>
#include<stack>
#include<stdio.h>
#include<string>
#include<tuple>
#include<vector>
//#include<bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define rep(i, x) for(ll i = 0; i < x; i++)
#define rep2(i, x) for(ll i = 1; i <= x; i++)
#define rep3(i, x, y) for(ll i = x; i < y; i++)
#define REP(i, x) for(ll i = x - 1; i >= 0; i--)
#define REP2(i, x) for(ll i = x; i >= 1; i--)
#define mpa make_pair
#define mpt make_tuple
#define emb emplace_back
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define puts(x) cout << (x) << "\n"
using ll = long long;
using ld = long double;
using namespace std;
const ll INF = 1000000000000000000;
const int intINF = 1000000000;
const ll mod = 1000000007;
const ll MOD = 998244353;
const ld pi = acos(-1);
//const ld EPS = 1e-9;
typedef string::const_iterator State;
class ParseError {};

template <typename T>
bool chmax(T& a, const T& b) {
	if (a < b) {
		a = b;  // aをbで更新
		return true;
	}
	return false;
}
// aよりもbが小さいならばaをbで更新する
// (更新されたならばtrueを返す)
template <typename T>
bool chmin(T& a, const T& b) {
	if (a > b) {
		a = b;  // aをbで更新
		return true;
	}
	return false;
}

bool isprime(int p) {
	if (p == 1) return false;
	for (int i = 2; i < p; i++) {
		if (p % i == 0) return false;
	}
	return true;
}
//エラトステネスの篩
vector<bool> isprime_format(ll n) {
	vector<bool> P(n + 1, 1); P[0] = P[1] = 1;
	for (ll i = 2; i * i <= n; i++) {
		if (!P[i]) continue;
		for (int j = i + i; j <= n; j += i) P[j] = false;
	}
	return P;
}
vector<ll> prime_format(ll n) {
	vector<bool> P = isprime_format(n);
	vector<ll> ans;
	for (int i = 2; i <= n; i++) {
		if (P[i]) ans.push_back(i);
	}
	return ans;
}
ll gcd(ll a, ll b) {
	if (b == 0) { return a; }
	return gcd(b, a % b);
}
//ax + by = cが整数解をもつための必要十分条件は c が gcd(a,b) で割り切れること。
// 返り値: a と b の最大公約数
// ax + by = gcd(a, b) を満たす (x, y) が格納される
//main関数内に extGCD(a, b, x, y); でx, yに解が格納
ll extGCD(ll a, ll b, ll& x, ll& y) {
	if (b == 0) {
		x = 1;
		y = 0;
		return a;
	}
	ll d = extGCD(b, a % b, y, x);
	y -= a / b * x;
	return d;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
ll keta(ll n) {
	ll res = 0;
	while (n >= 1) {
		res++;
		//res += n % 10;

		n /= 10;
	}
	return res;
}
ll modpow(ll x, ll y, ll m) {
	ll res = 1;
	while (y) {
		if (y % 2) { res *= x; res %= m; }
		x = x * x % m; y /= 2;
	}
	return res;
}

const int nCkMAX = 500000;
ll fac[nCkMAX], finv[nCkMAX], inv[nCkMAX];//n!、1/n!、1/n
// テーブルを作る前処理
void nCkinit(ll m) {
	fac[0] = fac[1] = 1;
	finv[0] = finv[1] = 1;
	inv[1] = 1;
	for (int i = 2; i < nCkMAX; i++) {
		fac[i] = fac[i - 1] * i % m;
		inv[i] = m - inv[m % i] * (m / i) % m;
		finv[i] = finv[i - 1] * inv[i] % m;
	}
}
// 二項係数計算
ll nCk(ll n, ll k, ll m) {
	if (n < k) return 0;
	if (n < 0 || k < 0) return 0;
	return fac[n] * (finv[k] * finv[n - k] % m) % m;
}
//nが大きくてkが小さい時
//nCkMAXはk+2まででOK
ll nCk2(ll n, ll k, ll m) {
	ll res = 1;
	for (int i = n - k + 1; i <= n; i++) {
		res *= i; res %= m;
	}
	res = res * finv[k] % m;
	return res;
}

//xorshift　from 「ビット演算 (bit 演算) の使い方を総特集！ 」
//1~6まで出したいときは
//xorshift() % 6 + 1
unsigned int xorshift() {
	static unsigned int tx = 123456789, ty = 362436069, tz = 521288629, tw = 88675123;
	unsigned int tt = (tx ^ (tx << 11));
	tx = ty; ty = tz; tz = tw;
	return (tw = (tw ^ (tw >> 19)) ^ (tt ^ (tt >> 8)));
}


//printf("%.10f\n", n);
typedef pair <ll, ll> P;
typedef pair <ld, ll> pp;
ll dx[4] = { 1, 0, -1, 0 }, dy[4] = { 0, 1, 0, -1 };
char ds[4] = { 'd', 'r', 'u', 'l' };
char dl[4] = { 'D', 'R', 'U', 'L' };


vector<ll> spf;
void smallest_prime_factors(ll n) {
	spf.resize(n + 1); spf[1] = 1;
	for (int i = 2; i <= n; i++) {
		if (!spf[i]) {
			for (int j = i; j < n; j += i) { spf[j] = i; }
		}
	}
}
std::map<int, int> high_speed_prime_factor(int n) {
	std::map<int, int> res;
	while (n != 1) {
		res[spf[n]]++;
		n /= spf[n];
	}
	return res;
}

////////////////////////////////struct
struct Point {
	ll x, y;
};
bool operator<(const Point& a1, const Point& a2) {
	if (a1.x < a2.x) return true;
	if (a1.x > a2.x) return false;
	if (a1.y < a2.y) return true;
	return false;
}
struct status {
	//ll c;
	ll u;
	ll v;

	//bool operator<(const status& rhs) const { return c < rhs.c; };
	//bool operator>(const status& rhs) const { return c > rhs.c; };
	bool operator<(const status& rhs) const { return u < rhs.u; };
	bool operator>(const status& rhs) const { return u > rhs.u; };
};
void yesno(bool ok) {
	if (ok) { cout << "YES\n"; }
	else { cout << "NO\n"; }
}
struct edge {
	ll to; ll cost;
};

//O(ElogV)
//typedef pair<ll, ll>P; //firstは最短距離、secondは頂点番号

//dijkstra1 : UからとVから、全ての頂点へ行くときの最小コストを求める
vector<vector<ll>> d(213456, vector<ll>(2, INF));//xからtまでのコストd[t][x], x: 0:u、1:v
vector<edge> G[213456];//コスト
void dijkstra1(ll s, ll uv) {
	//uv : sがuなら0、vなら1
	priority_queue<P, vector<P>, greater<P> >que;
	d[s][uv] = 0; que.push(P(0, s));
	while (!que.empty()) {
		P p = que.top(); que.pop();
		int v = p.second;
		if (d[v][uv] < p.first) { continue; }
		for (int i = 0; i < G[v].size(); i++) {
			edge e = G[v][i];
			if (d[e.to][uv] > d[v][uv] + e.cost) {
				d[e.to][uv] = d[v][uv] + e.cost;
				que.push(P(d[e.to][uv], e.to));
			}
		}
	}
}

//dijkstra2
//sからtまでの最小コストでの経路を求めつつ、
//sからある頂点aまでの経路の[Uとの距離が最小であるような]頂点とUの距離が最小となるような経路を選んだ時の{Uの距離,Vの距離}をuvcost[a][0]に格納
//Vも同じ
//それだけじゃ駄目であることがわかtt
//ある経路のUまでの距離とVまでの距離の合計が最小になるやつもとろうuvcost[a][2]

ll d2[213456];//始点sから終点tまでのコストd[t]
//uvcost[t][x](x 0:U, 1:V)=↓
//sからtまでの[xとの距離が最も小さくなるような]経路において、{Uの距離,Vの距離}
vector<vector<status>> uvcost(213456, vector<status>(3, { INF, INF }));
void dijkstra2(ll s) {
	//greater<P>を指定→firstが小さい順
	priority_queue<P, vector<P>, greater<P> >que;
	fill(d2, d2 + 213456, INF);//←TLE気を付ける
	d2[s] = 0; que.push(P(0, s));
	while (!que.empty()) {
		P p = que.top(); que.pop();
		int v = p.second;
		if (d2[v] < p.first) { continue; }
		for (int i = 0; i < G[v].size(); i++) {
			edge e = G[v][i];

			//頂点e.toに来たのでそこのU,Vの距離を反映させる
			status su = uvcost[v][0], sv = uvcost[v][1], sm = uvcost[v][2];
			chmin(su.u, d[e.to][0]); chmin(su.v, d[e.to][1]);
			chmin(sv.u, d[e.to][0]); chmin(sv.v, d[e.to][1]);
			chmin(sm.u, d[e.to][0]); chmin(sm.v, d[e.to][1]);

			if (d2[e.to] == d2[v] + e.cost) {
				if (uvcost[e.to][0] > su) {
					uvcost[e.to][0] = su;
				}
				if (uvcost[e.to][1].v > sv.v || ((uvcost[e.to][1].v == sv.v)&&(uvcost[e.to][1].u > sv.u))) {
					uvcost[e.to][1] = sv;
				}
				if (uvcost[e.to][2].u + uvcost[e.to][2].v > sm.u + sm.v) {
					uvcost[e.to][2] = sm;
				}
			}
			if (d2[e.to] > d2[v] + e.cost) {
				//そもそもS-T間が最初の運賃じゃないといけない
				uvcost[e.to][0] = su; uvcost[e.to][1] = sv; uvcost[e.to][2] = sm;
				d2[e.to] = d2[v] + e.cost;
				que.push(P(d2[e.to], e.to));
			}
		}
	}
}

int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	//cout << fixed << setprecision(15);
	//priority_queue<ll, vector<ll>, greater<ll>> que;
	//priority_queue<P, vector<P>, greater<P>> que;

	//定期券
	//最初にUとV始点でdijkstra
	//　全ての地点のU(V)との距離を知る
	//Sからdijkstra
	//　ある駅までの経路において、[Uまでの距離が最も小さかったもの]と、[V…]の2つを採用
	//　Tにたどり着いたときに[U…]と[V…]のUとVからの距離の合計が小さいほうを取って答え

	ll n, m; cin >> n >> m;
	ll s, t; cin >> s >> t;
	ll u, v; cin >> u >> v;
	rep(i, m) {
		ll a, b, c; cin >> a >> b >> c;
		G[a].push_back({ b,c });
		G[b].push_back({ a,c });
	}
	dijkstra1(u, 0); dijkstra1(v, 1);

	rep(i, 3) {
		uvcost[s][i] = { d[s][0],d[s][1] };
	}
	dijkstra2(s);

	ll mi = INF;
	rep(i, 3) {
		chmin(mi, uvcost[t][i].u + uvcost[t][i].v);
	}
	cout << min( mi, d[v][0] ) << endl;
	return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 54916
final_rank: 14

code_snippet: #include<iostream>
#include<algorithm>    
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<ctime>
#include<fstream>
#include<functional>
#include<map>
#include<math.h>
#include<numeric>
#include<queue>
#include<set>
#include<stack>
#include<stdio.h>
#include<string>
#include<tuple>
#include<vector>
//#include<bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#define rep(i, x) for(ll i = 0; i < x; i++)
#define rep2(i, x) for(ll i = 1; i <= x; i++)
#define rep3(i, x, y) for(ll i = x; i < y; i++)
#define REP(i, x) for(ll i = x - 1; i >= 0; i--)
#define REP2(i, x) for(ll i = x; i >= 1; i--)
#define mpa make_pair
#define mpt make_tuple
#define emb emplace_back
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define puts(x) cout << (x) << "\n"
using ll = long long;
using ld = long double;
using namespace std;
const ll INF = 1000000000000000000;
const int intINF = 1000000000;
const ll mod = 1000000007;
const ll MOD = 998244353;
const ld pi = acos(-1);
//const ld EPS = 1e-9;
typedef string::const_iterator State;
class ParseError {};

template <typename T>
bool chmax(T& a, const T& b) {
	if (a < b) {
		a = b;  // aをbで更新
		return true;
	}
	return false;
}
// aよりもbが小さいならばaをbで更新する
// (更新されたならばtrueを返す)
template <typename T>
bool chmin(T& a, const T& b) {
	if (a > b) {
		a = b;  // aをbで更新
		return true;
	}
	return false;
}

bool isprime(int p) {
	if (p == 1) return false;
	for (int i = 2; i < p; i++) {
		if (p % i == 0) return false;
	}
	return true;
}
//エラトステネスの篩
vector<bool> isprime_format(ll n) {
	vector<bool> P(n + 1, 1); P[0] = P[1] = 1;
	for (ll i = 2; i * i <= n; i++) {
		if (!P[i]) continue;
		for (int j = i + i; j <= n; j += i) P[j] = false;
	}
	return P;
}
vector<ll> prime_format(ll n) {
	vector<bool> P = isprime_format(n);
	vector<ll> ans;
	for (int i = 2; i <= n; i++) {
		if (P[i]) ans.push_back(i);
	}
	return ans;
}
ll gcd(ll a, ll b) {
	if (b == 0) { return a; }
	return gcd(b, a % b);
}
//ax + by = cが整数解をもつための必要十分条件は c が gcd(a,b) で割り切れること。
// 返り値: a と b の最大公約数
// ax + by = gcd(a, b) を満たす (x, y) が格納される
//main関数内に extGCD(a, b, x, y); でx, yに解が格納
ll extGCD(ll a, ll b, ll& x, ll& y) {
	if (b == 0) {
		x = 1;
		y = 0;
		return a;
	}
	ll d = extGCD(b, a % b, y, x);
	y -= a / b * x;
	return d;
}
ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}
ll keta(ll n) {
	ll res = 0;
	while (n >= 1) {
		res++;
		//res += n % 10;

		n /= 10;
	}
	return res;
}
ll modpow(ll x, ll y, ll m) {
	ll res = 1;
	while (y) {
		if (y % 2) { res *= x; res %= m; }
		x = x * x % m; y /= 2;
	}
	return res;
}

const int nCkMAX = 500000;
ll fac[nCkMAX], finv[nCkMAX], inv[nCkMAX];//n!、1/n!、1/n
// テーブルを作る前処理
void nCkinit(ll m) {
	fac[0] = fac[1] = 1;
	finv[0] = finv[1] = 1;
	inv[1] = 1;
	for (int i = 2; i < nCkMAX; i++) {
		fac[i] = fac[i - 1] * i % m;
		inv[i] = m - inv[m % i] * (m / i) % m;
		finv[i] = finv[i - 1] * inv[i] % m;
	}
}
// 二項係数計算
ll nCk(ll n, ll k, ll m) {
	if (n < k) return 0;
	if (n < 0 || k < 0) return 0;
	return fac[n] * (finv[k] * finv[n - k] % m) % m;
}
//nが大きくてkが小さい時
//nCkMAXはk+2まででOK
ll nCk2(ll n, ll k, ll m) {
	ll res = 1;
	for (int i = n - k + 1; i <= n; i++) {
		res *= i; res %= m;
	}
	res = res * finv[k] % m;
	return res;
}

//xorshift　from 「ビット演算 (bit 演算) の使い方を総特集！ 」
//1~6まで出したいときは
//xorshift() % 6 + 1
unsigned int xorshift() {
	static unsigned int tx = 123456789, ty = 362436069, tz = 521288629, tw = 88675123;
	unsigned int tt = (tx ^ (tx << 11));
	tx = ty; ty = tz; tz = tw;
	return (tw = (tw ^ (tw >> 19)) ^ (tt ^ (tt >> 8)));
}


//printf("%.10f\n", n);
typedef pair <ll, ll> P;
typedef pair <ld, ll> pp;
ll dx[4] = { 1, 0, -1, 0 }, dy[4] = { 0, 1, 0, -1 };
char ds[4] = { 'd', 'r', 'u', 'l' };
char dl[4] = { 'D', 'R', 'U', 'L' };


vector<ll> spf;
void smallest_prime_factors(ll n) {
	spf.resize(n + 1); spf[1] = 1;
	for (int i = 2; i <= n; i++) {
		if (!spf[i]) {
			for (int j = i; j < n; j += i) { spf[j] = i; }
		}
	}
}
std::map<int, int> high_speed_prime_factor(int n) {
	std::map<int, int> res;
	while (n != 1) {
		res[spf[n]]++;
		n /= spf[n];
	}
	return res;
}

////////////////////////////////struct
struct Point {
	ll x, y;
};
bool operator<(const Point& a1, const Point& a2) {
	if (a1.x < a2.x) return true;
	if (a1.x > a2.x) return false;
	if (a1.y < a2.y) return true;
	return false;
}
struct status {
	//ll c;
	ll u;
	ll v;

	//bool operator<(const status& rhs) const { return c < rhs.c; };
	//bool operator>(const status& rhs) const { return c > rhs.c; };
	bool operator<(const status& rhs) const { return u < rhs.u; };
	bool operator>(const status& rhs) const { return u > rhs.u; };
};
void yesno(bool ok) {
	if (ok) { cout << "YES\n"; }
	else { cout << "NO\n"; }
}
struct edge {
	ll to; ll cost;
};

//O(ElogV)
//typedef pair<ll, ll>P; //firstは最短距離、secondは頂点番号

//dijkstra1 : UからとVから、全ての頂点へ行くときの最小コストを求める
vector<vector<ll>> d(213456, vector<ll>(2, INF));//xからtまでのコストd[t][x], x: 0:u、1:v
vector<edge> G[213456];//コスト
void dijkstra1(ll s, ll uv) {
	//uv : sがuなら0、vなら1
	priority_queue<P, vector<P>, greater<P> >que;
	d[s][uv] = 0; que.push(P(0, s));
	while (!que.empty()) {
		P p = que.top(); que.pop();
		int v = p.second;
		if (d[v][uv] < p.first) { continue; }
		for (int i = 0; i < G[v].size(); i++) {
			edge e = G[v][i];
			if (d[e.to][uv] > d[v][uv] + e.cost) {
				d[e.to][uv] = d[v][uv] + e.cost;
				que.push(P(d[e.to][uv], e.to));
			}
		}
	}
}

//dijkstra2
//sからtまでの最小コストでの経路を求めつつ、
//sからある頂点aまでの経路の[Uとの距離が最小であるような]頂点とUの距離が最小となるような経路を選んだ時の{Uの距離,Vの距離}をuvcost[a][0]に格納
//Vも同じ
//それだけじゃ駄目であることがわかtt
//ある経路のUまでの距離とVまでの距離の合計が最小になるやつもとろうuvcost[a][2]

ll d2[213456];//始点sから終点tまでのコストd[t]
//uvcost[t][x](x 0:U, 1:V)=↓
//sからtまでの[xとの距離が最も小さくなるような]経路において、{Uの距離,Vの距離}
vector<vector<status>> uvcost(213456, vector<status>(3, { INF, INF }));
void dijkstra2(ll s) {
	//greater<P>を指定→firstが小さい順
	priority_queue<P, vector<P>, greater<P> >que;
	fill(d2, d2 + 213456, INF);//←TLE気を付ける
	d2[s] = 0; que.push(P(0, s));
	while (!que.empty()) {
		P p = que.top(); que.pop();
		int v = p.second;
		if (d2[v] < p.first) { continue; }
		for (int i = 0; i < G[v].size(); i++) {
			edge e = G[v][i];

			//頂点e.toに来たのでそこのU,Vの距離を反映させる
			status su = uvcost[v][0], sv = uvcost[v][1], sm = uvcost[v][2];
			chmin(su.u, d[e.to][0]); chmin(su.v, d[e.to][1]);
			chmin(sv.u, d[e.to][0]); chmin(sv.v, d[e.to][1]);
			chmin(sm.u, d[e.to][0]); chmin(sm.v, d[e.to][1]);

			if (d2[e.to] == d2[v] + e.cost) {
				if (uvcost[e.to][0] > su) {
					uvcost[e.to][0] = su;
				}
				if (uvcost[e.to][1].v > sv.v || ((uvcost[e.to][1].v == sv.v)&&(uvcost[e.to][1].u > sv.u))) {
					uvcost[e.to][1] = sv;
				}
				if (uvcost[e.to][2].u + uvcost[e.to][2].u > sm.u + sm.v) {
					uvcost[e.to][2] = sm;
				}
			}
			if (d2[e.to] > d2[v] + e.cost) {
				//そもそもS-T間が最初の運賃じゃないといけない
				uvcost[e.to][0] = su; uvcost[e.to][1] = sv; uvcost[e.to][2] = sm;
				d2[e.to] = d2[v] + e.cost;
				que.push(P(d2[e.to], e.to));
			}
		}
	}
}

int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	//cout << fixed << setprecision(15);
	//priority_queue<ll, vector<ll>, greater<ll>> que;
	//priority_queue<P, vector<P>, greater<P>> que;

	//定期券
	//最初にUとV始点でdijkstra
	//　全ての地点のU(V)との距離を知る
	//Sからdijkstra
	//　ある駅までの経路において、[Uまでの距離が最も小さかったもの]と、[V…]の2つを採用
	//　Tにたどり着いたときに[U…]と[V…]のUとVからの距離の合計が小さいほうを取って答え

	ll n, m; cin >> n >> m;
	ll s, t; cin >> s >> t;
	ll u, v; cin >> u >> v;
	rep(i, m) {
		ll a, b, c; cin >> a >> b >> c;
		G[a].push_back({ b,c });
		G[b].push_back({ a,c });
	}
	dijkstra1(u, 0); dijkstra1(v, 1);

	rep(i, 3) {
		uvcost[s][i] = { d[s][0],d[s][1] };
	}
	dijkstra2(s);

	ll mi = INF;
	rep(i, 3) {
		chmin(mi, uvcost[t][i].u + uvcost[t][i].v);
	}
	cout << min( mi, d[v][0] ) << endl;
	return 0;
}
accuracy: 0.9642857142857143
time_ms: 170
memory_kb: 54812
final_rank: 17

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 0650.cc: 定期券(Commuter Pass)
 */

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<utility>
 
using namespace std;

/* constant */

const int MAX_N = 100000;
const long long LINF = 1LL << 62;

/* typedef */

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,int> pli;
typedef vector<pii> vpii;

/* global variables */

vpii nbrs[MAX_N];
ll ds[MAX_N], dbus[MAX_N], dbvs[MAX_N];
ll gds[MAX_N * 4];
vi ps[MAX_N];

/* subroutines */

void dijkstra(int n, vpii nbrs[], ll ds[], int st, vi *ps = nullptr) {
  fill(ds, ds + n, LINF);
  ds[st] = 0;

  priority_queue<pli> q;
  q.push(pli(0, st));

  while (! q.empty()) {
    pli ue = q.top(); q.pop();
    ll ud = -ue.first;
    int u = ue.second;
    if (ds[u] != ud) continue;

    for (auto vw: nbrs[u]) {
      int v = vw.first;
      ll vd = ud + vw.second;
      if (ds[v] > vd) {
	ds[v] = vd;
	if (ps != nullptr) ps[v].assign(1, u);
	q.push(pli(-vd, v));
      }
      else if (ds[v] == vd)
	if (ps != nullptr) ps[v].push_back(u);
    }
  }
}

/* main */

int main() {
  int n, m, st, gl, bu, bv;
  scanf("%d%d%d%d%d%d", &n, &m, &st, &gl, &bu, &bv);
  st--, gl--, bu--, bv--;

  for (int i = 0; i < m; i++) {
    int u, v, w;
    scanf("%d%d%d", &u, &v, &w);
    u--, v--;
    nbrs[u].push_back(pii(v, w));
    nbrs[v].push_back(pii(u, w));
  }

  dijkstra(n, nbrs, ds, st, ps);
  dijkstra(n, nbrs, dbus, bu);
  dijkstra(n, nbrs, dbvs, bv);

  fill(gds, gds + n * 4, LINF);
  gds[gl << 2] = 0;

  priority_queue<pli> q;
  q.push(pli(0, gl << 2));

  while (! q.empty()) {
    pli ue = q.top(); q.pop();
    ll ud = -ue.first;
    int ug = ue.second;
    if (gds[ug] != ud) continue;

    int u = ug >> 2, ub = ug & 3;

    if (! (ub & 1)) {
      int vg = (u << 2) | (ub | 1);
      ll vd = ud + dbus[u];
      if (gds[vg] > vd)
	gds[vg] = vd, q.push(pli(-vd, vg));
    }
    if (! (ub & 2)) {
      int vg = (u << 2) | (ub | 2);
      ll vd = ud + dbvs[u];
      if (gds[vg] > vd)
	gds[vg] = vd, q.push(pli(-vd, vg));
    }

    for (auto v: ps[u]) {
      int vg = (v << 2) | ub;
      if (gds[vg] > ud)
	gds[vg] = ud, q.push(pli(-ud, vg));
    }
  }

  ll mind = min(dbus[bv], gds[(st << 2) | 3]);
  printf("%lld\n", mind);

  return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 30596
final_rank: 7

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
using namespace std;
 
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;
 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
 
 
#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()
 
#define MOD 1000000007
 
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-8, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;
 
  ModInt() : x(0) {}
 
  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
 
  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }
 
  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }
 
  ModInt operator-() const { return ModInt(-x); }
 
  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
 
  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
 
  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
 
  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
 
  bool operator==(const ModInt &p) const { return x == p.x; }
 
  bool operator!=(const ModInt &p) const { return x != p.x; }
 
  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
 
  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
 
  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }
 
  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }
 
  static int get_mod() { return mod; }
};
 
using modint = ModInt< 1000000007 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;
 
  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }
 
  inline T fact(int k) const { return _fact[k]; }
 
  inline T rfact(int k) const { return _rfact[k]; }
 
  inline T inv(int k) const { return _inv[k]; }
 
  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }
 
  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }
 
  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
 
ll modpow(ll x, ll n, ll mod) {
  ll res = 1;
  while(n) {
    if(n&1) res = (res * x) % mod;
    x = (x * x) % mod;
    n >>= 1;
  }
  return res;
} 
inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}
template<typename T> 
struct BIT{
  int N;
  std::vector<T> node;

  BIT(int n){
    N = n;
    node.resize(N+10);
  }

  /* a: 1-indexed */
  void add(int a, T x){
    for(int i=a; i<(int)node.size(); i += i & -i) node[i] += x;
  }

  /* [1, a] */
  T sum(int a){
    T res = 0;
    for(int x=a; x>0; x -= x & -x) res += node[x];
    return res;
  }

  /* [l, r] */
  T rangesum(int l, int r){
    return sum(r) - sum(l-1);
  }

  /* 
    a1+a2+...+aw >= valとなるような最小のwを返す
    @verify https://codeforces.com/contest/992/problem/E
  */
  int lower_bound(T val) {
    if(val < 0) return 0;

    int res = 0;
    int n = 1; 
    while (n < N) n *= 2;

    T tv=0;
    for (int k = n; k > 0; k /= 2) {
      if(res + k < N && node[res + k] < val){
        val -= node[res+k];
        res += k;
      }
    }
    return res+1; 
  }
};
struct UnionFind{
  std::vector<int> par;
  std::vector<int> siz;

  UnionFind(int sz_): par(sz_), siz(sz_) {
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  void init(int sz_){
    par.resize(sz_);
    siz.resize(sz_);
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  int root(int x){
    if(x == par[x]) return x;
    return par[x] = root(par[x]);
  }

  bool merge(int x, int y){
    x = root(x), y = root(y);
    if(x == y) return false;
    if(siz[x] < siz[y]) std::swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(int x, int y){
    return root(x) == root(y);
  }

  int size(int x){
    return siz[root(x)];
  }
};
struct RollingHash{

    using ull = unsigned long long;
    const ull mod = (1ULL << 61) - 1;
    const ull MASK30 = (1ULL << 30) - 1;
    const ull MASK31 = (1ULL << 31) - 1;

    const ull MASK61 = mod;

    ull base;
    int n;
    vector<ull> hash, pow;

    RollingHash(const string &s)
    {
        random_device rnd;
        mt19937_64 mt(rnd());
        base = calc_mod(mt()) % 100000 + 1000;
        
        n = (int)s.size();
        hash.assign(n+1, 0);
        pow.assign(n+1, 1);
        
        for(int i=0; i<n; i++){
            hash[i+1] = calc_mod(mul(hash[i], base) + s[i]);
            pow[i+1] = calc_mod(mul(pow[i], base));
        }
    }

    ull calc_mod(ull x){
        ull xu = x >> 61;
        ull xd = x & MASK61;
        ull res = xu + xd;
        if(res >= mod) res -= mod;
        return res;
    }

    ull mul(ull a, ull b){
        ull au = a >> 31;
        ull ad = a & MASK31;
        ull bu = b >> 31;
        ull bd = b & MASK31;
        ull mid = ad * bu + au * bd;
        ull midu = mid >> 30;
        ull midd = mid & MASK30;
        return calc_mod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    //[l,r)のハッシュ値
    inline ull get(int l, int r){
        ull res = calc_mod(hash[r] + mod*3-mul(hash[l], pow[r-l]));
        return res;
    }
    //string tのハッシュ値
    inline ull get(string t){
        ull res = 0;
        for(int i=0; i<t.size(); i++){
            res = calc_mod(mul(res, base)+t[i]);
        }
        return res;
    }
    //string s中のtの数をカウント
    inline int count(string t) {
        if(t.size() > n) return 0;
        auto hs = get(t);
        int res = 0;
        for(int i=0; i<n-t.size()+1; i++){
            if(get(i, i+t.size()) == hs) res++; 
        }
        return res;
    }

    /* 
        concat 
        @verify https://codeforces.com/problemset/problem/514/C
    */
    inline ull concat(ull h1, ull h2, int h2len){
      return calc_mod(h2 + mul(h1, pow[h2len]));
    }

    // LCPを求める S[a:] T[b:]
    inline int LCP(int a, int b){
        int len = min((int)hash.size()-a, (int)hash.size()-b);
        
        int lb = -1, ub = len;
        while(ub-lb>1){
            int mid = (lb+ub)/2;

            if(get(a, a+mid) == get(b, b+mid)) lb = mid;
            else ub = mid;
        }
        return lb;
    }
};

ll ds[101010], dt[101010];

ll d[4][101010];
vector<vector<pair<ll,ll>>> g(101010);
int main() {  
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);

  int N, M; cin >> N >> M;
  int S, T; cin >> S >> T;
  int U, V; cin >> U >> V;
  S--; T--; U--; V--;
  REP(i,N) ds[i] = dt[i]  = (1LL<<60);
  REP(i,M) {
    int a, b, c; cin >> a >> b >> c;
    a--; b--;
    g[a].push_back({b, c});
    g[b].push_back({a, c});
  }
  {
    priority_queue<pair<ll,ll>, vector<pair<ll,ll>>, greater<pair<ll,ll>>> pq;
    pq.push({0, S});
    ds[S] = 0;
    while(pq.size()) {
      auto[cost, v] = pq.top(); pq.pop();
      if(ds[v] < cost) continue;
      for(auto[u, c]: g[v]) {
        if(ds[u] > ds[v] + c) {
          ds[u] = ds[v] + c;
          pq.push({ds[u], u});
        }
      }
    }
  }
  {
    priority_queue<pair<ll,ll>, vector<pair<ll,ll>>, greater<pair<ll,ll>>> pq;
    pq.push({0, T});
    dt[T] = 0;
    while(pq.size()) {
      auto[cost, v] = pq.top(); pq.pop();
      if(dt[v] < cost) continue;
      for(auto[u, c]: g[v]) {
        if(dt[u] > dt[v] + c) {
          dt[u] = dt[v] + c;
          pq.push({dt[u], u});
        }
      }
    }
  }

  ll mi = ds[T];
  REP(i,N) d[0][i] = d[1][i] = d[2][i] = d[3][i] = (1LL<<60);
  d[0][U] = 0;

  priority_queue<pair<ll,pair<ll,ll>>, vector<pair<ll,pair<ll,ll>>>, greater<pair<ll,pair<ll,ll>>>> pq;
  pq.push({0, {0,U}});
  while(pq.size()) {
    
    auto[c, p] = pq.top(); pq.pop();
    auto[st, v] = p;
    if(d[st][v] < c) continue;
    for(auto[u, cost]: g[v]) {
      if(d[st][u] > d[st][v] + cost) {
          d[st][u] = d[st][v] + cost;
          pq.push({d[st][u], {st, u}});
        }

        if(st == 0 && (ds[v] + dt[u] + cost == mi || dt[v] + ds[u] + cost == mi)) {
          {
            queue<int> q; q.push(v);
            while(q.size()) {
              auto now = q.front(); q.pop();
              for(auto[nxt, cost2]: g[now]) {
                if(ds[now] + cost2 == ds[nxt] && (ds[now] + cost2 + dt[nxt] == mi || dt[now] + cost2 + ds[nxt] == mi) && d[1][nxt] > d[0][v]) {
                  d[1][nxt] = d[0][v];
                  pq.push({d[1][nxt], {1, nxt}});
                  q.push(nxt);
                }
              }
            }
          } 
          {
            queue<int> q; q.push(v);
            while(q.size()) {
              auto now = q.front(); q.pop();
              for(auto[nxt, cost2]: g[now]) {
                if(ds[now] - cost2 == ds[nxt] && (ds[now] + cost2 + dt[nxt] == mi || dt[now] + cost2 + ds[nxt] == mi) && d[2][nxt] > d[0][v]) {
                  d[2][nxt] = d[0][v];
                  pq.push({d[2][nxt], {2, nxt}});
                  q.push(nxt);
                }
              }
            }
          }
        }
      
    }
  }
 
  cout << min({d[1][V], d[0][V], d[2][V]}) << endl;
  return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 36440
final_rank: 11

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
using namespace std;
 
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;
 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
 
 
#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()
 
#define MOD 1000000007
 
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-8, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;
 
  ModInt() : x(0) {}
 
  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
 
  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }
 
  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }
 
  ModInt operator-() const { return ModInt(-x); }
 
  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
 
  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
 
  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
 
  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
 
  bool operator==(const ModInt &p) const { return x == p.x; }
 
  bool operator!=(const ModInt &p) const { return x != p.x; }
 
  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
 
  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
 
  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }
 
  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }
 
  static int get_mod() { return mod; }
};
 
using modint = ModInt< 1000000007 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;
 
  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }
 
  inline T fact(int k) const { return _fact[k]; }
 
  inline T rfact(int k) const { return _rfact[k]; }
 
  inline T inv(int k) const { return _inv[k]; }
 
  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }
 
  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }
 
  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
 
ll modpow(ll x, ll n, ll mod) {
  ll res = 1;
  while(n) {
    if(n&1) res = (res * x) % mod;
    x = (x * x) % mod;
    n >>= 1;
  }
  return res;
} 
inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}
template<typename T> 
struct BIT{
  int N;
  std::vector<T> node;

  BIT(int n){
    N = n;
    node.resize(N+10);
  }

  /* a: 1-indexed */
  void add(int a, T x){
    for(int i=a; i<(int)node.size(); i += i & -i) node[i] += x;
  }

  /* [1, a] */
  T sum(int a){
    T res = 0;
    for(int x=a; x>0; x -= x & -x) res += node[x];
    return res;
  }

  /* [l, r] */
  T rangesum(int l, int r){
    return sum(r) - sum(l-1);
  }

  /* 
    a1+a2+...+aw >= valとなるような最小のwを返す
    @verify https://codeforces.com/contest/992/problem/E
  */
  int lower_bound(T val) {
    if(val < 0) return 0;

    int res = 0;
    int n = 1; 
    while (n < N) n *= 2;

    T tv=0;
    for (int k = n; k > 0; k /= 2) {
      if(res + k < N && node[res + k] < val){
        val -= node[res+k];
        res += k;
      }
    }
    return res+1; 
  }
};
struct UnionFind{
  std::vector<int> par;
  std::vector<int> siz;

  UnionFind(int sz_): par(sz_), siz(sz_) {
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  void init(int sz_){
    par.resize(sz_);
    siz.resize(sz_);
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  int root(int x){
    if(x == par[x]) return x;
    return par[x] = root(par[x]);
  }

  bool merge(int x, int y){
    x = root(x), y = root(y);
    if(x == y) return false;
    if(siz[x] < siz[y]) std::swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(int x, int y){
    return root(x) == root(y);
  }

  int size(int x){
    return siz[root(x)];
  }
};
struct RollingHash{

    using ull = unsigned long long;
    const ull mod = (1ULL << 61) - 1;
    const ull MASK30 = (1ULL << 30) - 1;
    const ull MASK31 = (1ULL << 31) - 1;

    const ull MASK61 = mod;

    ull base;
    int n;
    vector<ull> hash, pow;

    RollingHash(const string &s)
    {
        random_device rnd;
        mt19937_64 mt(rnd());
        base = calc_mod(mt()) % 100000 + 1000;
        
        n = (int)s.size();
        hash.assign(n+1, 0);
        pow.assign(n+1, 1);
        
        for(int i=0; i<n; i++){
            hash[i+1] = calc_mod(mul(hash[i], base) + s[i]);
            pow[i+1] = calc_mod(mul(pow[i], base));
        }
    }

    ull calc_mod(ull x){
        ull xu = x >> 61;
        ull xd = x & MASK61;
        ull res = xu + xd;
        if(res >= mod) res -= mod;
        return res;
    }

    ull mul(ull a, ull b){
        ull au = a >> 31;
        ull ad = a & MASK31;
        ull bu = b >> 31;
        ull bd = b & MASK31;
        ull mid = ad * bu + au * bd;
        ull midu = mid >> 30;
        ull midd = mid & MASK30;
        return calc_mod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    //[l,r)のハッシュ値
    inline ull get(int l, int r){
        ull res = calc_mod(hash[r] + mod*3-mul(hash[l], pow[r-l]));
        return res;
    }
    //string tのハッシュ値
    inline ull get(string t){
        ull res = 0;
        for(int i=0; i<t.size(); i++){
            res = calc_mod(mul(res, base)+t[i]);
        }
        return res;
    }
    //string s中のtの数をカウント
    inline int count(string t) {
        if(t.size() > n) return 0;
        auto hs = get(t);
        int res = 0;
        for(int i=0; i<n-t.size()+1; i++){
            if(get(i, i+t.size()) == hs) res++; 
        }
        return res;
    }

    /* 
        concat 
        @verify https://codeforces.com/problemset/problem/514/C
    */
    inline ull concat(ull h1, ull h2, int h2len){
      return calc_mod(h2 + mul(h1, pow[h2len]));
    }

    // LCPを求める S[a:] T[b:]
    inline int LCP(int a, int b){
        int len = min((int)hash.size()-a, (int)hash.size()-b);
        
        int lb = -1, ub = len;
        while(ub-lb>1){
            int mid = (lb+ub)/2;

            if(get(a, a+mid) == get(b, b+mid)) lb = mid;
            else ub = mid;
        }
        return lb;
    }
};

ll ds[101010], dt[101010];

ll d[2][101010];
vector<vector<pair<ll,ll>>> g(101010);
int main() {  
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);

  int N, M; cin >> N >> M;
  int S, T; cin >> S >> T;
  int U, V; cin >> U >> V;
  S--; T--; U--; V--;
  REP(i,N) ds[i] = dt[i]  = (1LL<<60);
  REP(i,M) {
    int a, b, c; cin >> a >> b >> c;
    a--; b--;
    g[a].push_back({b, c});
    g[b].push_back({a, c});
  }
  {
    priority_queue<pair<ll,ll>, vector<pair<ll,ll>>, greater<pair<ll,ll>>> pq;
    pq.push({0, S});
    ds[S] = 0;
    while(pq.size()) {
      auto[cost, v] = pq.top(); pq.pop();
      if(ds[v] < cost) continue;
      for(auto[u, c]: g[v]) {
        if(ds[u] > ds[v] + c) {
          ds[u] = ds[v] + c;
          pq.push({ds[u], u});
        }
      }
    }
  }
  {
    priority_queue<pair<ll,ll>, vector<pair<ll,ll>>, greater<pair<ll,ll>>> pq;
    pq.push({0, T});
    dt[T] = 0;
    while(pq.size()) {
      auto[cost, v] = pq.top(); pq.pop();
      if(dt[v] < cost) continue;
      for(auto[u, c]: g[v]) {
        if(dt[u] > dt[v] + c) {
          dt[u] = dt[v] + c;
          pq.push({dt[u], u});
        }
      }
    }
  }

  ll mi = ds[T];
  REP(i,N) d[0][i] = d[1][i] = (1LL<<60);
  d[0][U] = 0;
  priority_queue<pair<ll,pair<ll,ll>>, vector<pair<ll,pair<ll,ll>>>, greater<pair<ll,pair<ll,ll>>>> pq;
  pq.push({0, {0,U}});
  while(pq.size()) {
    auto[c, p] = pq.top(); pq.pop();
    auto[st, v] = p;
    if(d[st][v] < c) continue;
    for(auto[u, cost]: g[v]) {
      if(d[st][u] > d[st][v] + cost) {
          d[st][u] = d[st][v] + cost;
          pq.push({d[st][u], {st, u}});
        }

        if(st == 0 && (ds[v] + dt[u] + cost == mi || dt[v] + ds[u] + cost == mi)) {
          
          if(ds[v] < ds[u]) {
            
            if(d[1][u] > d[0][v]) {
              d[1][u] = d[0][v];
              pq.push({d[1][u],{1,u}});
            }
            {
              int now = u;
              bool update = true;
              while(now != T && update) {
                update = false;
                for(auto [nxt, cost2]: g[now]) {
                  if(ds[now] + cost2 == ds[nxt] && ds[now] + dt[nxt] + cost2 == mi && d[1][nxt] > d[0][v]) {
                    d[1][nxt] = d[0][v];
                    pq.push({d[1][nxt], {1, nxt}});
                    now = nxt;
                    update = true;
                    break;
                  }
                }
              }
            }
            {
              int now = v;
              bool update = true;
              while(now != S && update) {
                update = false;
                for(auto [nxt, cost2]: g[now]) {
                  if(ds[now] - cost2 == ds[nxt] && ds[now] + dt[nxt] + cost2 == mi && d[1][nxt] > d[0][v]) {
                    d[1][nxt] = d[0][v];
                    pq.push({d[1][nxt], {1, nxt}});
                    now = nxt;
                    update = true;
                    break;
                  }
                }
              }
            }
          }else{
            if(d[1][u] > d[0][v]) {
              d[1][u] = d[0][v];
              pq.push({d[1][u],{1,u}});
            }
            {
              int now = u;
              bool update = true;
              while(now != T && update) {
                update = false;
                for(auto [nxt, cost2]: g[now]) {
                  if(ds[now] - cost2 == ds[nxt]&& ds[now] + dt[nxt] + cost2 == mi && d[1][nxt] > d[0][v]) {
                    d[1][nxt] = d[0][v];
                    pq.push({d[1][nxt], {1, nxt}});
                    now = nxt;
                    update = true;
                    break;
                  }
                }
              }
            }
            {
              int now = v;
              bool update = true;
              while(now != S && update) {
                update = false;
                for(auto [nxt, cost2]: g[now]) {
                  if(ds[now] + cost2 == ds[nxt]&& ds[now] + dt[nxt] + cost2 == mi && d[1][nxt] > d[0][v]) {
                    d[1][nxt] = d[0][v];
                    pq.push({d[1][nxt], {1, nxt}});
                    now = nxt;
                    update = true;
                    break;
                  }
                }
              }
            }
          }
        }
      
    }
  }
 
  cout << min({d[1][V], d[0][V]}) << endl;
  return 0;
}
accuracy: 0.19642857142857142
time_ms: 150
memory_kb: 29924
final_rank: 20

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
using namespace std;
 
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;
 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
 
 
#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()
 
#define MOD 1000000007
 
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-8, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;
 
  ModInt() : x(0) {}
 
  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
 
  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }
 
  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }
 
  ModInt operator-() const { return ModInt(-x); }
 
  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
 
  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
 
  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
 
  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
 
  bool operator==(const ModInt &p) const { return x == p.x; }
 
  bool operator!=(const ModInt &p) const { return x != p.x; }
 
  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
 
  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
 
  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }
 
  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }
 
  static int get_mod() { return mod; }
};
 
using modint = ModInt< 1000000007 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;
 
  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }
 
  inline T fact(int k) const { return _fact[k]; }
 
  inline T rfact(int k) const { return _rfact[k]; }
 
  inline T inv(int k) const { return _inv[k]; }
 
  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }
 
  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }
 
  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
 
ll modpow(ll x, ll n, ll mod) {
  ll res = 1;
  while(n) {
    if(n&1) res = (res * x) % mod;
    x = (x * x) % mod;
    n >>= 1;
  }
  return res;
} 
inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}
template<typename T> 
struct BIT{
  int N;
  std::vector<T> node;

  BIT(int n){
    N = n;
    node.resize(N+10);
  }

  /* a: 1-indexed */
  void add(int a, T x){
    for(int i=a; i<(int)node.size(); i += i & -i) node[i] += x;
  }

  /* [1, a] */
  T sum(int a){
    T res = 0;
    for(int x=a; x>0; x -= x & -x) res += node[x];
    return res;
  }

  /* [l, r] */
  T rangesum(int l, int r){
    return sum(r) - sum(l-1);
  }

  /* 
    a1+a2+...+aw >= valとなるような最小のwを返す
    @verify https://codeforces.com/contest/992/problem/E
  */
  int lower_bound(T val) {
    if(val < 0) return 0;

    int res = 0;
    int n = 1; 
    while (n < N) n *= 2;

    T tv=0;
    for (int k = n; k > 0; k /= 2) {
      if(res + k < N && node[res + k] < val){
        val -= node[res+k];
        res += k;
      }
    }
    return res+1; 
  }
};
struct UnionFind{
  std::vector<int> par;
  std::vector<int> siz;

  UnionFind(int sz_): par(sz_), siz(sz_) {
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  void init(int sz_){
    par.resize(sz_);
    siz.resize(sz_);
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  int root(int x){
    if(x == par[x]) return x;
    return par[x] = root(par[x]);
  }

  bool merge(int x, int y){
    x = root(x), y = root(y);
    if(x == y) return false;
    if(siz[x] < siz[y]) std::swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(int x, int y){
    return root(x) == root(y);
  }

  int size(int x){
    return siz[root(x)];
  }
};
struct RollingHash{

    using ull = unsigned long long;
    const ull mod = (1ULL << 61) - 1;
    const ull MASK30 = (1ULL << 30) - 1;
    const ull MASK31 = (1ULL << 31) - 1;

    const ull MASK61 = mod;

    ull base;
    int n;
    vector<ull> hash, pow;

    RollingHash(const string &s)
    {
        random_device rnd;
        mt19937_64 mt(rnd());
        base = calc_mod(mt()) % 100000 + 1000;
        
        n = (int)s.size();
        hash.assign(n+1, 0);
        pow.assign(n+1, 1);
        
        for(int i=0; i<n; i++){
            hash[i+1] = calc_mod(mul(hash[i], base) + s[i]);
            pow[i+1] = calc_mod(mul(pow[i], base));
        }
    }

    ull calc_mod(ull x){
        ull xu = x >> 61;
        ull xd = x & MASK61;
        ull res = xu + xd;
        if(res >= mod) res -= mod;
        return res;
    }

    ull mul(ull a, ull b){
        ull au = a >> 31;
        ull ad = a & MASK31;
        ull bu = b >> 31;
        ull bd = b & MASK31;
        ull mid = ad * bu + au * bd;
        ull midu = mid >> 30;
        ull midd = mid & MASK30;
        return calc_mod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    //[l,r)のハッシュ値
    inline ull get(int l, int r){
        ull res = calc_mod(hash[r] + mod*3-mul(hash[l], pow[r-l]));
        return res;
    }
    //string tのハッシュ値
    inline ull get(string t){
        ull res = 0;
        for(int i=0; i<t.size(); i++){
            res = calc_mod(mul(res, base)+t[i]);
        }
        return res;
    }
    //string s中のtの数をカウント
    inline int count(string t) {
        if(t.size() > n) return 0;
        auto hs = get(t);
        int res = 0;
        for(int i=0; i<n-t.size()+1; i++){
            if(get(i, i+t.size()) == hs) res++; 
        }
        return res;
    }

    /* 
        concat 
        @verify https://codeforces.com/problemset/problem/514/C
    */
    inline ull concat(ull h1, ull h2, int h2len){
      return calc_mod(h2 + mul(h1, pow[h2len]));
    }

    // LCPを求める S[a:] T[b:]
    inline int LCP(int a, int b){
        int len = min((int)hash.size()-a, (int)hash.size()-b);
        
        int lb = -1, ub = len;
        while(ub-lb>1){
            int mid = (lb+ub)/2;

            if(get(a, a+mid) == get(b, b+mid)) lb = mid;
            else ub = mid;
        }
        return lb;
    }
};

ll ds[101010], dt[101010];

ll d[3][101010];
vector<vector<pair<ll,ll>>> g(101010);
int main() {  
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);

  int N, M; cin >> N >> M;
  int S, T; cin >> S >> T;
  int U, V; cin >> U >> V;
  S--; T--; U--; V--;
  REP(i,N) ds[i] = dt[i]  = (1LL<<60);
  REP(i,M) {
    int a, b, c; cin >> a >> b >> c;
    a--; b--;
    g[a].push_back({b, c});
    g[b].push_back({a, c});
  }
  {
    priority_queue<pair<ll,ll>, vector<pair<ll,ll>>, greater<pair<ll,ll>>> pq;
    pq.push({0, S});
    ds[S] = 0;
    while(pq.size()) {
      auto[cost, v] = pq.top(); pq.pop();
      if(ds[v] < cost) continue;
      for(auto[u, c]: g[v]) {
        if(ds[u] > ds[v] + c) {
          ds[u] = ds[v] + c;
          pq.push({ds[u], u});
        }
      }
    }
  }
  {
    priority_queue<pair<ll,ll>, vector<pair<ll,ll>>, greater<pair<ll,ll>>> pq;
    pq.push({0, T});
    dt[T] = 0;
    while(pq.size()) {
      auto[cost, v] = pq.top(); pq.pop();
      if(dt[v] < cost) continue;
      for(auto[u, c]: g[v]) {
        if(dt[u] > dt[v] + c) {
          dt[u] = dt[v] + c;
          pq.push({dt[u], u});
        }
      }
    }
  }

  ll mi = ds[T];
  REP(i,N) d[0][i] = d[1][i] = d[2][i] = (1LL<<60);
  d[0][U] = 0;
  priority_queue<pair<ll, pair<int, int>>, vector<pair<ll, pair<int, int>>>, greater<pair<ll, pair<int, int>>>> pq;
  pq.push({0, {0, U}});
  while(pq.size()) {
    auto[c, p] = pq.top(); pq.pop();
    auto[st, v] = p;
    if(d[st][v] < c) continue;
    for(auto [u, cost]: g[v]) {
      if(ds[v] + dt[u] + cost == mi || dt[v] + ds[u] + cost == mi) {
        if(st == 0) {
          cost = 0;
          int nxt = st;
          if(ds[v] < ds[u]) nxt = 1;
          else nxt = 2;
          if(d[nxt][u] > d[st][v] + cost) {
            d[nxt][u] = d[st][v] + cost;
            pq.push({d[nxt][u], {nxt, u}});
          }
        }else if(st == 1){
          if(ds[v] < ds[u]) cost = 0;
          if(d[st][u] > d[st][v] + cost) {
            d[st][u] = d[st][v] + cost;
            pq.push({d[st][u], {st, u}});
          }
        }else if(st == 2) {
          if(ds[v] > ds[u]) cost = 0;
          if(d[st][u] > d[st][v] + cost) {
            d[st][u] = d[st][v] + cost;
            pq.push({d[st][u], {st, u}});
          }
        }
      }else{
        if(d[st][u] > d[st][v] + cost) {
          d[st][u] = d[st][v] + cost;
          pq.push({d[st][u], {st, u}});
        }
      }
    }
  }
  cout << min({d[0][V], d[1][V], d[2][V]}) << endl;
  return 0;
}
accuracy: 0.625
time_ms: 190
memory_kb: 26488
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("O2")
using namespace std;
using ll = long long int;
#define F first
#define S second
#define fast_io ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
const int N=1e5+10,LN=20,SQ=550,M=5e4+10;
const ll INF=1e18;
const int MOD=1000000007 /*998244353*/;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using pll=pair<ll,ll>;
using pii=pair<int,int>;
#define ordered_set tree<pair<pll,ll>, null_type,less<pair<pll,ll>>, rb_tree_tag,tree_order_statistics_node_update>
ll pow(ll x, ll y, ll mod){
    ll ans=1;
    while (y != 0) {
        if (y & 1) ans = ans * x % mod;
        y >>= 1;
        x = x * x % mod;
    }
    return ans;
}
ll n,m,S,T,U,V,dp[2][N],du[4][N],ans=INF;
vector<pii> adj[N];
vector<int> in[N],out[N];
bitset<N> fl,sp;
void dfs(ll v){
    fl[v]=1;
    for(ll u : out[v]){
        if(!fl[u]) dfs(u);
        dp[0][v]=min(dp[0][v],dp[0][u]);
    }
}
void sfd(ll v){
    fl[v]=1;
    for(ll u : in[v]){
        if(!fl[u]) sfd(u);
        dp[1][v]=min(dp[1][v],dp[1][u]);
    }
}
void di(ll x, ll t){
    priority_queue<pair<ll,int>> q;
    q.push({0,x});
    du[t][x]=0;
    while(!q.empty()){
        ll v=q.top().S;
        q.pop();
        for(pll p : adj[v]){
            if(du[t][p.F]<=du[t][v]+p.S) continue;
            du[t][p.F]=du[t][v]+p.S;
            q.push({-du[t][p.F],p.F});
        }
    }
}
int main(){
    fast_io;
    memset(du,127,sizeof du);
    cin >> n >> m >> S >> T >> U >> V;
    for(ll i=0; i<m; i++){
        ll v,u,c;
        cin >> v >> u >> c;
        adj[v].emplace_back(u,c);
        adj[u].emplace_back(v,c);
    }
    di(S,0);
    di(T,1);
    di(U,2);
    di(V,3);
    for(ll i=1; i<=n; i++) dp[0][i]=dp[1][i]=du[3][i];
    for(ll i=1; i<=n; i++){
        if(du[0][i]+du[1][i]==du[0][T]) sp[i]=1;
        for(pll p : adj[i]){
            if(du[0][i]+p.S+du[1][p.F]==du[0][T]) out[i].push_back(p.F),in[p.F].push_back(i);
        }
    }
    for(ll i=1; i<=n; i++) if(sp[i] && !fl[i]) dfs(i);
    fl=0;
    for(ll i=1; i<=n; i++) if(sp[i] && !fl[i]) sfd(i);
    for(ll i=1; i<=n; i++) if(sp[i]) ans=min(ans,min(dp[0][i],dp[1][i])+du[2][i]);
    cout << min(ans,du[2][V]) << '\n';
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 27384
final_rank: 4

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

typedef long long int ll;
typedef pair<int, int> pii;
 
#define SZ(x)                       (int) x.size()
#define F                           first
#define S                           second

const int N = 2e5 + 10, MOD = 1e9 + 7;
ll dist[4][N], dp[2][N], M[N], X[N], n, m, R = 1e18, B, E, U, V;
vector<pii> adj[N]; vector<int> out[N], in[N];

void dijk(int S, int t) {
	fill(dist[t], dist[t] + N, 1e18);
	dist[t][S] = 0;
	priority_queue<pair<ll, int>> pq;
	pq.push({dist[t][S], S});
	while (SZ(pq)) {
		int v = pq.top().S; pq.pop();
		for (pii u : adj[v]) {
			if (dist[t][u.F] > dist[t][v] + u.S) {
				dist[t][u.F] = dist[t][v] + u.S;
				pq.push({-dist[t][u.F], u.F});
			}
		}
	}
}

void add_edge(int u, int v) {
	out[u].push_back(v);
	in[v].push_back(u);
}

void DFS(int v) {
	M[v] = 1;
	for (int u : out[v]) {
		if (!M[u]) DFS(u);
		dp[0][v] = min(dp[0][v], dp[0][u]);
	}
}

void SFD(int v) {
	M[v] = 1;
	for (int u : in[v]) {
		if (!M[u]) SFD(u);
		dp[1][v] = min(dp[1][v], dp[1][u]);
	}
}

int main() {
	scanf("%lld%lld%lld%lld%lld%lld", &n, &m, &B, &E, &U, &V);
	for (int i = 1; i <= m; i++) {
		int u, v, w; scanf("%d%d%d", &u, &v, &w);
		adj[u].push_back({v, w});
		adj[v].push_back({u, w});
	}
	dijk(B, 0);
	dijk(E, 1);
	dijk(U, 2);
	dijk(V, 3);
	for (int i = 1; i <= n; i++) {
		if (dist[0][i] + dist[1][i] == dist[0][E]) X[i] = 1;
		for (pii u : adj[i]) {
			if (dist[0][i] + u.S + dist[1][u.F] == dist[0][E]) {
				add_edge(i, u.F);
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		dp[0][i] = dp[1][i] = dist[3][i];
	}
	for (int i = 1; i <= n; i++) {
		if (X[i] && !M[i]) DFS(i);
	}
	fill(M, M + N, 0);
	for (int i = 1; i <= n; i++) {
		if (X[i] && !M[i]) SFD(i);
	}/*
	for (int i = 1; i <= n; i++) {
        printf("%lld %lld\n", dp[0][i], dp[1][i]);
    }*/
	for (int i = 1; i <= n; i++) {
		if (X[i]) {
			R = min(R, min(dp[0][i], dp[1][i]) + dist[2][i]);
		}
	}
	printf("%lld\n", min(R, dist[2][V]));
	return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 42288
final_rank: 12

code_snippet: #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>

#include <algorithm>
#include <functional>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <iostream>
#include <limits>
#include <numeric>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

struct Node {
    int u;
    ll step;

    Node(int u, ll step) : u(u), step(step) {}

    bool operator>(const Node& rhs) const { return step > rhs.step; }
};

struct Edge {
    int v, w;
    Edge* next;
};

const int N = 100010, M = 200010;

int n, m;
int s, t, a, b;
ll ans;
Edge* g[N];
bool vis[N];
ll diss[N], disa[N], disb[N], da[N], db[N];

void adde(int u, int v, int w);
void runspt(int s, ll* dis);
void dfs(int u);

int main() {
    scanf("%d%d%d%d%d%d", &n, &m, &s, &t, &a, &b);
    while (m--) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        adde(u, v, w);
        adde(v, u, w);
    }
    runspt(a, disa);
    ans = disa[b];
    if (disa[s] != -1) {
        runspt(b, disb);
        runspt(s, diss);
        dfs(t);
    }
    printf("%lld\n", ans);
    return 0;
}

void dfs(int u) {
    if (vis[u])
        return;
    vis[u] = true;
    da[u] = disa[u];
    db[u] = disb[u];
    for (Edge* p = g[u]; p; p = p->next)
        if (diss[p->v] + p->w == diss[u]) {
            dfs(p->v);
            da[u] = min(da[u], da[p->v]);
            db[u] = min(db[u], db[p->v]);
        }
    ans = min(ans, min(da[u] + disb[u], db[u] + disa[u]));
}

void runspt(int s, ll* dis) {
    memset(dis, -1, sizeof(ll) * (n + 1));
    priority_queue<Node, vector<Node>, greater<Node>> q;
    q.emplace(s, dis[s] = 0);
    while (!q.empty()) {
        Node tmp = q.top();
        q.pop();
        if (tmp.step != dis[tmp.u])
            continue;
        for (Edge* p = g[tmp.u]; p; p = p->next)
            if (dis[p->v] == -1 || dis[p->v] > tmp.step + p->w)
                q.emplace(p->v, dis[p->v] = tmp.step + p->w);
    }
}

void adde(int u, int v, int w) {
    static Edge pool[M * 2];
    static Edge* p = pool;
    p->v = v;
    p->w = w;
    p->next = g[u];
    g[u] = p;
    ++p;
}
accuracy: 1
time_ms: 140
memory_kb: 16444
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <algorithm>
using namespace std;

long long N, M, S, T, U, V, A[1 << 18], B[1 << 18], C[1 << 18], dist[1 << 18], dp1[1 << 18], dp2[1 << 18];
long long dista[1 << 18], distb[1 << 18], distc[1 << 18], distd[1 << 18];
vector<pair<long long, long long>>X[1 << 18];
int Order[1 << 18];

vector<long long>getdist(int pos) {
	priority_queue<pair<long long, long long>, vector<pair<long long, long long>>, greater<pair<long long, long long>>>Q;
	for (int i = 1; i <= N; i++) dist[i] = (1LL << 60);
	Q.push(make_pair(0, pos)); dist[pos] = 0;

	while (!Q.empty()) {
		int pos = Q.top().second; long long cost = Q.top().first; Q.pop();
		for (int i = 0; i < X[pos].size(); i++) {
			int to = X[pos][i].first; long long tm = X[pos][i].second;
			if (dist[to] > cost + tm) {
				dist[to] = cost + tm;
				Q.push(make_pair(dist[to], to));
			}
		}
	}
	vector<long long>E;
	for (int i = 1; i <= N; i++) E.push_back(dist[i]);
	return E;
}

int main() {
	cin >> N >> M >> S >> T >> U >> V;
	for (int i = 0; i < M; i++) {
		cin >> A[i] >> B[i] >> C[i];
		X[A[i]].push_back(make_pair(B[i], C[i]));
		X[B[i]].push_back(make_pair(A[i], C[i]));
	}
	vector<long long>A1 = getdist(S); for (int i = 1; i <= N; i++) dista[i] = A1[i - 1];
	vector<long long>A2 = getdist(T); for (int i = 1; i <= N; i++) distb[i] = A2[i - 1];
	vector<long long>A3 = getdist(U); for (int i = 1; i <= N; i++) distc[i] = A3[i - 1];
	vector<long long>A4 = getdist(V); for (int i = 1; i <= N; i++) distd[i] = A4[i - 1];

	vector<pair<long long, long long>>vec1;
	for (int i = 1; i <= N; i++) { if (dista[i] + distb[i] == dista[T]) vec1.push_back(make_pair(dista[i], i)); }
	sort(vec1.begin(), vec1.end());

	for (int i = 1; i <= N; i++) { dp1[i] = (1LL << 60); dp2[i] = (1LL << 60); Order[i] = -1; }
	for (int i = 0; i < vec1.size(); i++) Order[vec1[i].second] = i;

	for (int i = 0; i < vec1.size(); i++) {
		int pos = vec1[i].second; dp1[pos] = min(dp1[pos], distc[pos]);
		for (int j = 0; j < X[pos].size(); j++) {
			if (Order[X[pos][j].first] != -1 && Order[X[pos][j].first] > i) {
				dp1[X[pos][j].first] = min(dp1[X[pos][j].first], dp1[pos]);
			}
		}
	}
	for (int i = vec1.size() - 1; i >= 0; i--) {
		int pos = vec1[i].second; dp2[pos] = min(dp2[pos], distc[pos]);
		for (int j = 0; j < X[pos].size(); j++) {
			if (Order[X[pos][j].first] != -1 && Order[X[pos][j].first] < i) {
				dp2[X[pos][j].first] = min(dp2[X[pos][j].first], dp2[pos]);
			}
		}
	}

	long long ans = distc[V];
	for (int i = 1; i <= N; i++) ans = min(ans, min(dp1[i], dp2[i]) + distd[i]);
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 310
memory_kb: 36596
final_rank: 13

code_snippet: #include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <queue>
#include <tuple>

template <class T>
using MinHeap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

using lint = long long;
constexpr lint INF = 1LL << 50;

struct Edge {
    int dst;
    lint cost;
    explicit Edge(int dst, lint cost) : dst(dst), cost(cost) {}
};

using Graph = std::vector<std::vector<Edge>>;

std::vector<lint> dijkstra(const Graph& graph, int r) {
    std::vector<lint> dist(graph.size(), INF);
    dist[r] = 0;
    MinHeap<std::pair<lint, int>> que;
    que.emplace(dist[r], r);

    while (!que.empty()) {
        lint d;
        int v;
        std::tie(d, v) = que.top();
        que.pop();
        if (dist[v] < d) continue;

        for (auto e : graph[v]) {
            int u = e.dst;
            lint nd = d + e.cost;
            if (dist[u] > nd) {
                dist[u] = nd;
                que.emplace(nd, u);
            }
        }
    }

    return dist;
}

void solve() {
    int n, m, s, t, a, b;
    std::cin >> n >> m >> s >> t >> a >> b;
    --s, --t, --a, --b;

    Graph graph(n);
    while (m--) {
        int u, v;
        lint c;
        std::cin >> u >> v >> c;
        --u, --v;
        graph[u].emplace_back(v, c);
        graph[v].emplace_back(u, c);
    }

    auto ds = dijkstra(graph, s),
         da = dijkstra(graph, a),
         db = dijkstra(graph, b);

    std::vector<int> vs(n);
    std::iota(vs.begin(), vs.end(), 0);
    std::sort(vs.begin(), vs.end(),
              [&](int u, int v) { return ds[u] < ds[v]; });

    std::vector<std::vector<lint>>
        dist(3, std::vector<lint>(n, INF));

    for (auto v : vs) {
        dist[0][v] = da[v];
        dist[1][v] = db[v];
        dist[2][v] = da[v] + db[v];

        for (auto e : graph[v]) {
            int u = e.dst;
            if (ds[u] + e.cost > ds[v]) continue;
            for (int k = 0; k < 3; ++k) {
                dist[k][v] = std::min(dist[k][v], dist[k][u]);
            }
        }

        dist[2][v] = std::min({dist[2][v],
                               dist[0][v] + db[v],
                               dist[1][v] + da[v]});
    }

    std::cout << std::min(da[b], dist[2][t]) << std::endl;
}

int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 21392
final_rank: 3

code_snippet: #include <bits/stdc++.h>
 
//    #include <boost/multiprecision/cpp_int.hpp>
 #define int long long
 #define inf  1000000007
 #define pa pair<int,int>
 #define ll long long
 #define pal pair<double,double>
 #define ppap pair<pa,int>
  #define PI 3.14159265358979323846
  #define paa pair<int,char>
  #define  mp make_pair
  #define  pb push_back
  #define EPS (1e-8)
                                          
    int dx[8]={0,1,0,-1,1,1,-1,-1};
    int dy[8]={1,0,-1,0,-1,1,1,-1};
                                            using namespace std;
                                   			class pa3{
                                            	public:
                                            	int x;
                                   				int y,z;
                                            	pa3(int x=0,int y=0,int z=0):x(x),y(y),z(z) {}
                                            	bool operator < (const pa3 &p) const{
                                            		if(x!=p.x) return x<p.x;
                                            		if(y!=p.y) return y<p.y;
                                            		 return z<p.z;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                   				bool operator > (const pa3 &p) const{
                                            		if(x!=p.x) return x>p.x;
                                            		if(y!=p.y) return y>p.y;
                                            		 return z>p.z;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa3 &p) const{
                                            		return x==p.x && y==p.y && z==p.z;
                                            	}
                                            		bool operator != (const pa3 &p) const{
                                            			return !( x==p.x && y==p.y && z==p.z);
                                            	}
                                            
                                            };
                                            
                                            class pa4{
                                            	public:
                                            	int x;
                                            	int y,z,w;
                                            	pa4(int x=0,int y=0,int z=0,int w=0):x(x),y(y),z(z),w(w) {}
                                            	bool operator < (const pa4 &p) const{
                                            		if(x!=p.x) return x<p.x;
                                            		if(y!=p.y) return y<p.y;
                                            		if(z!=p.z)return z<p.z;
                                            		return w<p.w;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator > (const pa4 &p) const{
                                            		if(x!=p.x) return x>p.x;
                                            		if(y!=p.y) return y>p.y;
                                            		if(z!=p.z)return z>p.z;
                                            		return w>p.w;
                                            		//return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa4 &p) const{
                                            		return x==p.x && y==p.y && z==p.z &&w==p.w;
                                            	}
                                            		
                                            
                                            };
                                            class pa2{
                                            	public:
                                            	int x,y;
                                            	pa2(int x=0,int y=0):x(x),y(y) {}
                                            	pa2 operator + (pa2 p) {return pa2(x+p.x,y+p.y);}
                                            	pa2 operator - (pa2 p) {return pa2(x-p.x,y-p.y);}
                                            	bool operator < (const pa2 &p) const{
                                            		return y != p.y ? y<p.y: x<p.x;
                                            	}
                                            	bool operator > (const pa2 &p) const{
                                            		return x != p.x ? x<p.x: y<p.y;
                                            	}
                                            	bool operator == (const pa2 &p) const{
                                            		return abs(x-p.x)==0 && abs(y-p.y)==0;
                                            	}
                                            	bool operator != (const pa2 &p) const{
                                            		return !(abs(x-p.x)==0 && abs(y-p.y)==0);
                                            	}
                                            		
                                            
                                            };
                                            
 
                      
                                string itos( int i ) {
                                ostringstream s ;
                                s << i ;
                                return s.str() ;
                                }
                                 
                                int gcd(int v,int b){
                                	if(v==0) return b;
                                	if(b==0) return v;
                                	if(v>b) return gcd(b,v);
                                	if(v==b) return b;
                                	if(b%v==0) return v;
                                	return gcd(v,b%v);
                                }
                 
                            
                                int mod;
int extgcd(int a, int b, int &x, int &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    int d = extgcd(b, a%b, y, x);
    y -= a/b * x;
    return d;
}
pa operator+(const pa & l,const pa & r) {   
    return {l.first+r.first,l.second+r.second};                                    
}    
pa operator-(const pa & l,const pa & r) {   
    return {l.first-r.first,l.second-r.second};                                    
}  
                                
                int pr[10000100];
                int inv[10000010];
                
                int beki(int wa,int rr,int warukazu){
                	if(rr==0) return 1%warukazu;
                	if(rr==1) return wa%warukazu;
                	wa%=warukazu;
                	if(rr%2==1) return ((ll)beki(wa,rr-1,warukazu)*(ll)wa)%warukazu;
                	ll zx=beki(wa,rr/2,warukazu);
                	return (zx*zx)%warukazu;
                }
 
                
    			int comb(int nn,int rr){
    				if(rr<0 || rr>nn || nn<0) return 0;
    				int r=pr[nn]*inv[rr];
    				r%=mod;
    				r*=inv[nn-rr];
    				r%=mod;
    				return r;
    			}
               
                void gya(int ert){
                	pr[0]=1;
                	for(int i=1;i<=ert;i++){
                		pr[i]=(pr[i-1]*i)%mod;
                	}
                		inv[ert]=beki(pr[ert],mod-2,mod);
                	for(int i=ert-1;i>=0;i--){
                		inv[i]=inv[i+1]*(i+1)%mod;
                	}
                }
                
              //   cin.tie(0);
    		//	ios::sync_with_stdio(false);
    			//priority_queue<pa3,vector<pa3>,greater<pa3>> pq;            
                 //sort(ve.begin(),ve.end(),greater<int>());
 //   mt19937(clock_per_sec);
  //  mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()) ;
      
       



vector<pa> G[100020];

int dis[100020][4];

int n;
void dij(int r,int po){
	for(int i=1;i<=n;i++)dis[i][po]=-1;
	priority_queue<pa,vector<pa>,greater<pa>> pq;   
	pq.push(mp(0,r));
	while(pq.size()){
		pa z=pq.top();
		pq.pop();
		if(dis[z.second][po]>=0) continue;
		dis[z.second][po]=z.first;
		for(auto v:G[z.second])pq.push(mp(z.first+v.second,v.first));
	}
}



vector<int> G1[100020];
vector<int> G2[100020];

int nyu[100020]={};
int use[100020]={};

int ue[100020][2];
int si[100020][2];
signed main(){
	
	
   cin.tie(0);
	ios::sync_with_stdio(false);
	int m;
cin>>n>>m;
	int S,T,U,V;
	cin>>S>>T>>U>>V;
	
	for(int i=0;i<m;i++){
		int y,yy,yyy;
		cin>>y>>yy>>yyy;
		G[y].pb(mp(yy,yyy));
		G[yy].pb(mp(y,yyy));
		
	}
	dij(S,0);
	dij(T,1);
	dij(U,2);
	dij(V,3);
	
	int ST=dis[T][0];
	
	for(int i=1;i<=n;i++)for(auto v:G[i]){
		int s=i,t=v.first,val=v.second;
		if(dis[s][0]+dis[t][1]+val==ST){
			G1[s].pb(t);
			G2[t].pb(s);
			nyu[t]++;
			use[s]=1,use[t]=1;
			
		}
	}
	queue<int> qu;
	for(int i=1;i<=n;i++)if(use[i])if(nyu[i]==0)qu.push(i);
	vector<int> topo;
	while(qu.size()){
		int y=qu.front();
		qu.pop();
		topo.pb(y);
		for(auto v:G1[y]){
			nyu[v]--;
			if(nyu[v]==0)qu.push(v);
		}
	}
	
	for(auto v:topo){
		ue[v][0]=dis[v][2];
		ue[v][1]=dis[v][3];
		
		for(auto r:G2[v]){
			ue[v][0]=min(ue[v][0],ue[r][0]);
			ue[v][1]=min(ue[v][1],ue[r][1]);
			
		}
	}
	reverse(topo.begin(),topo.end());
	for(auto v:topo){
		si[v][0]=dis[v][2];
		si[v][1]=dis[v][3];
		
		for(auto r:G1[v]){
			si[v][0]=min(si[v][0],si[r][0]);
			si[v][1]=min(si[v][1],si[r][1]);
			
		}
	}
	int ans=dis[U][3];
	for(int i=1;i<=n;i++)if(use[i]==1){
		ans=min({ans,ue[i][0]+si[i][1],si[i][0]+ue[i][1]});
	
	}
	cout<<ans<<endl;
	return 0;
	

 
 }
accuracy: 1
time_ms: 380
memory_kb: 36588
final_rank: 15

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

using ll = long long;

struct edge{
    int to;
    ll cost;
};

struct node{
    int id;
    ll cost;

    bool operator<(const node &rhs) const {
        return cost > rhs.cost;
    }
};

int dfs(int v, const vector< vector<int> > &g, vector<int> &dp){
    if(dp[v] >= 0){
        return dp[v];
    }

    int res = 0;
    for(auto to : g[v]){
        res |= dfs(to, g, dp);
    }

    return dp[v] = res;
}

ll dijkstra(int s, int t, const vector< vector<edge> > &g){
    vector<ll> cost(g.size(), 1LL << 62);
    priority_queue<node> que;
    que.push({s, 0LL});
    cost[s] = 0;
    while(!que.empty()){
        node now = que.top();
        que.pop();
        if(cost[now.id] < now.cost){
            continue;
        }
        for(auto e : g[now.id]){
            if(cost[e.to] > now.cost + e.cost){
                cost[e.to] = now.cost + e.cost;
                que.push({e.to, now.cost + e.cost});
            }
        }
    }

    return cost[t];
}

int main(){
    int n, m, s, t, u, v;
    cin >> n >> m >> s >> t >> u >> v;
    --s;
    --t;
    --u;
    --v;

    vector< vector<edge> > g(n), g1(n), g2(n);
    for(int i = 0 ; i < m ; ++i){
        int a, b;
        ll c;
        cin >> a >> b >> c;
        --a;
        --b;
        g[a].push_back({b, c});
        g[b].push_back({a, c});
        g1[a].push_back({b, c});
        g1[b].push_back({a, c});
        g2[a].push_back({b, c});
        g2[b].push_back({a, c});
    }

    vector< vector<int> > prev(n);
    vector<ll> cost(n, 1LL << 62);
    priority_queue<node> que;
    que.push({s, 0LL});
    cost[s] = 0;
    while(!que.empty()){
        node now = que.top();
        que.pop();
        if(cost[now.id] < now.cost){
            continue;
        }
        for(auto e : g[now.id]){
            if(cost[e.to] == now.cost + e.cost){
                prev[e.to].emplace_back(now.id);
            }else if(cost[e.to] > now.cost + e.cost){
                prev[e.to].clear();
                prev[e.to].emplace_back(now.id);
                cost[e.to] = now.cost + e.cost;
                que.push({e.to, now.cost + e.cost});
            }
        }
    }

    vector< vector<int> > g3(n);
    for(int i = 0 ; i < n ; ++i){
        for(auto j : prev[i]){
            g3[j].emplace_back(i);
        }
    }

    vector<int> dp(n, -1);
    dp[t] = 1;
    dfs(s, g3, dp);

    for(int i = 0 ; i < n ; ++i){
        for(auto j : prev[i]){
            if(dp[i] == 1 && dp[j] == 1){
                g1[i].push_back({j, 0LL});
                g2[j].push_back({i, 0LL});
            }
        }
    }

    ll ans = min({dijkstra(u, v, g1), dijkstra(v, u, g1), dijkstra(u, v, g2), dijkstra(v, u, g2)});
    cout << ans << endl;

    return 0;
}
accuracy: 0.625
time_ms: 570
memory_kb: 65640
final_rank: 19