#ifdef LOCAL
#include ".debug.hpp"
#else
#define debug(...) 42
#endif
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
using namespace std;
using ordered_set = tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>;
/*** Basic DSU template ***/
struct DSU {
int n;
vector<int> parent, component_size; // # parameters
DSU(int _n) { // # initial defining parameters
n = _n, parent.resize(n + 5), component_size.assign(n + 5, 1);
for (int i = 1; i <= n; i++) parent[i] = i;
}
inline int findpar(int node) { // # findpar function returns parent(ancestor) of node
if (node == parent[node]) return node;
return parent[node] = findpar(parent[node]);
}
inline bool unionset(int u, int v) { // # unionset function just unions two different components
u = findpar(u), v = findpar(v);
if (u == v) return false;
if (component_size[u] < component_size[v]) swap(u, v);
component_size[u] += component_size[v], parent[v] = u;
return true;
}
};
const int MXN = 1e5 + 5;
const int64_t INF = 1e18;
set<array<int, 2>> MST[MXN];
int par[MXN], N;
int64_t dist[MXN];
bool vis[MXN];
void dfs(const int &node) {
for (auto &[child, cost]: MST[node]) if (child != par[node]) par[child] = node, dist[child] = dist[node] + cost, dfs(child);
}
// void dijkstra(const int &root) {
// for (int i = 1; i <= N; i++) dist[i] = INF, vis[i] = false;
// priority_queue<array<int64_t, 2>, vector<array<int64_t, 2>>, greater<array<int64_t, 2>>> pq;
// pq.push({0, root}), dist[root] = 0;
// while (!pq.empty()) {
// int node = pq.top()[1]; pq.pop();
// if (vis[node]) continue;
// vis[node] = true;
// for (auto &child : adj[node])
// }
// }
signed main() {
#ifndef VOID
cin.tie(nullptr)->sync_with_stdio(false);
#endif
int M, S, T, U, V; cin >> N >> M >> S >> T >> U >> V;
vector<array<int, 3>> edges;
for (int i = 0, u, v, c; i < M; i++) cin >> u >> v >> c, edges.push_back({u, v, c});
sort(edges.begin(), edges.end(), [&](const array<int, 3> &x, const array<int, 3> &y) -> bool {
return x[2] < y[2];
});
DSU dsu(N);
map<array<int, 2>, int> mp;
for (auto &[u, v, c] : edges)
if (dsu.unionset(u, v)) MST[u].insert({v, c}), MST[v].insert({u, c}), mp[{u, v}] = mp[{v, u}] = c;
dfs(S);
while (T != S) {
int cost = mp[{par[T], T}];
MST[par[T]].erase({T, cost}), MST[T].erase({par[T], cost}), MST[par[T]].insert({T, 0}), MST[T].insert({par[T], 0});
T = par[T];
}
for (int i = 1; i <= N; i++) par[i] = 0, dist[i] = 0;
dfs(U);
cout << dist[V];
return 0;
}