//Kruskal最小生成树
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+5;
int fa[maxn],n,m;
int _find(int x){
return fa[x]==x?x:fa[x]=_find(fa[x]);
}
void _union(int x,int y){
int fx=_find(x),fy=_find(y);
if(fx=fy){
return;
}
fa[fx]=fy;
}
struct edge{
int u,v,val;
}e[maxn];
bool cmp(edge x,edge y){
return x.val<y.val;
}
int main() {
cin>>n>>m;
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++){
cin>>e[i].u>>e[i].v>>e[i].val;
}
//关键步骤1:将所有边按权值从小到大排序
sort(e+1,e+m+1,cmp);
int ans=0,cnt=0;//ans:最小生成树的总权值,cnt:已选边的数量
//关键步骤2:遍历所有边
for(int i=1;i<=m;i++){
int u=e[i].u,v=e[i].v;//如果边的两个端点已在同一个连通分量 ,跳过
if(_find(u)=_find(v)) continue;
_union(u,v);//合并两个端点所在连通分量
ans+=e[i].val,cnt++;
}
//判断是否形成生成树:边数应为节点-1;
if(cnt!=n-1) cout<<"orz"<<endl;//图不连通
else cout<<ans<<endl;//输出最小生成树权值和
}