#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(); }