#include <stdio.h>
struct edge
{
int u;
int v;
int w;
};
int f[7],sum=0,cnt=0,n,m;//f数组大小根据n的值决定;
struct edge t,e[10];//e数组的值由m的值决定。
//快速排序
void quicksort(int left,int right)
{
int i,j;
if(left>right)
return;
i=left,j=right;
int temp=e[left].w;
while(i!=j)
{
while(e[j].w>=temp&&i<j)
j--;
while(e[i].w<=temp&&i<j)
i++;
if(i<j)
{
t=e[i],e[i]=e[j];e[j]=t;
}
}
t=e[i],e[i]=e[left],e[left]=t;
quicksort(left,i-1);
quicksort(i+1,right);
return;
}
void init()
{
for(int i=1;i<=n;i++)
f[i]=i;
return;
}
//找爹,直到找到祖宗,擒贼先擒王。
int getf(int v)
{
if(f[v]==v)
return v;
else
{
//路径压缩,每次函数返回的时候,把路上遇到的人的BOSS改为最后找到的祖宗编号。
f[v]=getf(f[v]);
return f[v];
}
}
//合并两子集合的函数
int merge(int x,int y)
{
int t1,t2;
t1=getf(x);
t2=getf(y);
if(t1!=t2)
{
f[t2]=t1; //靠左原则,左边变为右边的BOSS
return 1;
}
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
quicksort(1,m);
init();
//Kruskal算法核心
for(int i=1;i<m;i++)//开始从小到大枚举每一条边。
{
//判断一条边的两个顶点是否已经联通,即判断是否在一个集合中
if(merge(e[i].u,e[i].v))//如果目前尚未不连通,则选用这条边。
{
cnt++;
sum+=e[i].w;
}
if(cnt==n-1)//直到选用n-1条边后退出循环。
break;
}
printf("%d\n",sum);
return 0;
}
/*
6 9
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2
*/
//#define debug
struct node{
int u,v,w;
};
bool cmp(const node& a,const node& b){
return a.w<b.w;
}
int fa[1005];
int get_father(int x){
return fa[x]=fa[x]==x?x:get_father(fa[x]);
}
int main()
{
#ifdef debug
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // debug
node mmp[15005];
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=0;i<m;i++){
scanf("%d%d%d",&mmp[i].u,&mmp[i].v,&mmp[i].w);
}
sort(mmp,mmp+m,cmp);
int ans=0;
for(int i=1;i<=n;i++) fa[i]=i;
int cnt=0;
for(int i=0;i<m;i++){
if(get_father(mmp[i].u)!=get_father(mmp[i].v)){
ans+=mmp[i].w;
fa[fa[mmp[i].u]]=fa[mmp[i].v];
cnt++;
if(cnt==n-1){
break;
}
}
}
printf("%d\n",ans);
}
return 0;
}