#include using namespace std; typedef long long ll; const int INF=0x3f3f3f3f; const ll LLINF=0x3f3f3f3f3f3f3f3fLL; const int MAX=2e5+10; struct Disjoint_Set_Union { int pre[MAX],sz[MAX]; void init(int n) { int i; for(i=1;i<=n;i++) { pre[i]=i; sz[i]=1; } } int find(int x) { if(pre[x]!=x) pre[x]=find(pre[x]); return pre[x]; } bool merge(int x,int y,bool dir=false) { x=find(x); y=find(y); if(x==y) return 0; if(!dir && sz[x]>sz[y]) swap(x,y); pre[x]=y; // x -> y sz[y]+=sz[x]; return 1; } }dsu; struct Kruskal { #define type ll #define inf LLINF struct edge{int x,y;type w;}; vector e; void init(){e.clear();} void add_edge(int a,int b,type w){e.push_back({a,b,w});} type work(int n) { int i,cnt; type res=0; dsu.init(n); sort(e.begin(),e.end(),[&](edge x,edge y){ return x.w>y.w; }); for(auto &it:e) { if(dsu.merge(it.x,it.y)) res+=it.w; } return res; } #undef type #undef inf }krsk; int main() { int n,m,i,a,b,c; scanf("%d%d",&n,&m); krsk.init(); while(m--) { scanf("%d%d%d",&a,&b,&c); krsk.add_edge(a,b,c); } printf("%lld\n",2*krsk.work(n)); return 0; }