#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define reg register
#define LL long long
using namespace std;
const int maxN = 100005, maxM = 300005;
inline int read() {
int x = 0; char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return x;
}
int N, M;
LL Ans = 1e18, MST;
struct Edge {
int dis, nxt, to;
}e[maxM << 1]; int cnte = 1, head[maxN];
inline void add_Edge(int i, int j, int k) {
e[++cnte].dis = k, e[cnte].nxt = head[i], e[cnte].to = j, head[i] = cnte;
}
int fa[maxN];
int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);}
void merge(int x, int y) {fa[find(x)] = find(y);}
struct EE {
int u, v, w;
bool is;
}E[maxM];
bool cmp(EE x, EE y) {
return x.w < y.w;
}
void Init() {
N = read(), M = read();
for(reg int i = 1; i <= M; ++i) {
E[i].u = read(), E[i].v = read(), E[i].w = read();
}
}
void Kruskal() {
int cnt = 0;
sort(E + 1, E + M + 1, cmp);
for(int i = 1; i <= N; ++i) fa[i] = i;
for(reg int i = 1; i <= M; ++i) {
reg int u = E[i].u, v = E[i].v, w = E[i].w;
if(u == v) {
E[i].is = true;
continue;
}
if(find(u) != find(v)) {
add_Edge(u, v, w), add_Edge(v, u, w);
merge(u, v), ++cnt,
E[i].is = true,
MST += w;
}
if(cnt == N - 1) break;
}
}
int g[maxN][30], dep[maxN], f[maxN][30], h[maxN][30];
//g数组是最大值,h数组是严格次大值
void dfs(int u, int father) {
for(reg int v, i = head[u]; i; i = e[i].nxt) {
if((v = e[i].to) == father) continue;
dep[v] = dep[u] + 1,
f[v][0] = u, h[v][0] = g[v][0] = e[i].dis,
dfs(v, u);
}
}
void Pre() {
memset(h, -0x7f, sizeof(h)),
memset(g, -0x7f, sizeof(g));
dep[1] = 1, f[1][0] = 1;
dfs(1, 0);
for(int i = 1; i <= 21; ++i) {
for(int u = 1; u <= N; ++u) {
f[u][i] = f[f[u][i - 1]][i - 1],
//注意一下处理
g[u][i] = max(g[u][i - 1], g[f[u][i - 1]][i - 1]),
h[u][i] = min(g[u][i - 1], g[f[u][i - 1]][i - 1]);
if(i == 1) continue;
if(g[u][i - 1] == g[f[u][i - 1]][i - 1]) {
h[u][i] = max(h[u][i - 1], h[f[u][i - 1]][i - 1]);
}
else {
h[u][i] = max(h[u][i], h[u][i - 1]),
h[u][i] = max(h[u][i], h[f[u][i - 1]][i - 1]);
}
}
}
}
int LCA(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
for(int i = 20; i >= 0; --i) if(dep[f[x][i]] >= dep[y]) x = f[x][i];
if(x == y) return x;
for(int i = 20; i >= 0; --i) if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
return f[x][0];
}
int Query(int down, int up, int now) {
int ret = -1e18;
for(int i = 20; i >= 0; --i) {
if(dep[f[down][i]] >= dep[up]) {
if(now != g[down][i]) ret = max(ret, g[down][i]);
else ret = max(ret, h[down][i]);
down = f[down][i];
}
}
return ret;
}
void Solve() {
Pre();
for(int i = 1; i <= M; ++i) {
if(E[i].is) continue;
int x = E[i].u, y = E[i].v;
int lca = LCA(x, y), k;
k = Query(x, lca, E[i].w), k = max(k, Query(y, lca, E[i].w));
if(k == E[i].w) continue;
Ans = min(Ans, MST + (E[i].w - k));
}
printf("%lld\n", Ans);
}
int main() {
Init();
Kruskal();
Solve();
return 0;
}