#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
#define maxsize 100010
int noderoot[maxsize]; //用来存每个节点的根
int rank[maxsize]; //用来存树的高度
typedef struct {
int a,b,price; //a,b代表一条边的两个端点,price代表这个边的权值
}Node;
Node a[maxsize]; //定义maxsize个边
//初始化n个节点的信息;
void Init(int n){
for(int i=0;i<=n;i++){
noderoot[i]=i; //初始化时默认每个节点的根是他自己
rank[i]=0; //初始化时因为只有一个单节点,默认每个结点的高度是0
}
}
int find(int x){
int root=x;
while(root!=noderoot[root])
root=noderoot[root];
while(x!=root){
int t=noderoot[x];
noderoot[x]=root;
x=t;
}
return root;
}
void unite(int x,int y){
x=find(x);
y=find(y);
if(rank[x]<rank[y]){
noderoot[x]=y;
}
else{
noderoot[y]=x;
if(rank[x]==rank[y]) rank[x]++;
}
}
int cmp(const void*a,const void*b){
return ((Node*)a)->price-((Node*)b)->price;
}
int kruskal(int n,int m){
int nEdge=0,cnt=0;
qsort(a,m,sizeof(a[0]),cmp);
int i;
for(i=0;i<m&&nEdge!=n-1;i++){
if(find(a[i].a)!=find(a[i].b)){
unite(a[i].a,a[i].b);
cnt+=a[i].price;
nEdge++;
}
}
if(nEdge<n-1) cnt=-1;
return cnt;
}
int main(){
int n,m,cnt;
cin>>n>>m;
Init(n);
for(int i=0;i<m;i++){
scanf("%d %d %d",&a[i].a,&a[i].b,&a[i].price);
a[i].a--;
a[i].b--;
}
cnt=kruskal(n,m);
cout<<cnt;
return 0;
}