#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
struct edge{
int a,b,w;
bool operator < (const edge &b) const{
return w<b.w;
}
}edges[N];
int n,m;
int p[N];
int ffind (int x){
if(p[x]!=x) p[x]=ffind(p[x]);
return p[x];
}
void kruskal(){
int ans=0;
for(int i=0;i<m;){
//从i开始 找到所有与i的权值相等的边 最后一个是j-1
int j=i;
for(;j<m;j++){
auto [a,b,w]=edges[j];
if(edges[i].w==w) {
if(ffind(a)!=ffind(b)){
ans+=w;
}
}else break;
}
//已经找到权值相等的边 从中挑出必须保留的边 从ans中删去
//因为ans存的是需要删除的边 所以需要保留的边要从中删去
for(;i<j;i++){
auto [a,b,w]=edges[i];
a=ffind(a),b=ffind(b);//注意要把值赋给a,b 否则下面p[a]=b就错了
if(a!=b){
p[a]=b;
ans-=w;
}
}
}
cout<<ans<<endl;
}
signed main(){
cin>>n>>m;
for(int i=0;i<m;i++){
int a,b,c;
cin>>a>>b>>c;
edges[i]={a,b,c};
}
sort(edges,edges+m);
for(int i=1;i<=n;i++) p[i]=i;
kruskal();
}