/*
题意,删除边使得图在进行最小生成树时,最小生成树唯一
当多个边的权值相同且多条边分别相连的两个点集(树)相同,则认为两条边等价,只保留其中一条
考虑到权值大小连续,从第i条边向后遍历,若
ff(li[i].u)==ff(li[l].u)&&ff(li[i].v)==ff(li[l].v)
或
ff(li[i].u)==ff(li[l].v)&&ff(li[i].v)==ff(li[l].u)
成立时,则说明两条边等价,答案添加边l的边权并继续向后遍历直到边权与i不同,随后再合并两个子树。
*/
#include <bits/stdc++.h>
#define ll long long
#define pii pair<int, int>
using namespace std;
struct lin {
int u;
int v;
ll val;
bool used;
} li[500001];
int fa[300001];
bool cmp(lin a, lin b) {
return a.val < b.val;
}
int ff(int x) {
if (fa[x] == 0)
fa[x] = x;
if (fa[x] == x)
return x;
return fa[x] = ff(fa[x]);
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
int u, v, val;
scanf("%d%d%d", &u, &v, &val);
li[i].u = u;
li[i].v = v;
li[i].val = val;
}
sort(li + 1, li + 1 + m, cmp);
ll ans = 0;
int cnt = 0;
set<ll> st;
for (int i = 1; i <= m; i++) {
int u = li[i].u;
int v = li[i].v;
ll val = li[i].val;
if (ff(u)==ff(v)){
continue;
}
int l = i + 1;
while(li[l].val==li[i].val){
if(((ff(li[l].u)==ff(u)&&ff(li[l].v)==ff(v))||(ff(li[l].v)==ff(u)&&ff(li[l].u)==ff(v)))){
ans += li[l].val;
}
l++;
}
st.insert(val);
li[i].used = 1;
fa[ff(v)] = ff(u);
cnt++;
}
printf("%lld", ans);
}
//https://ac.nowcoder.com/acm/contest/26077/1009