#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int p[N];//保存并查集
int res;//权重之和
int n, m;
int cnt;//树的边数
struct E{
int a;//起始点
int b;//终止点
int w;//权重
bool operator < (const E& rhs)//通过边长进行升序
{
return this->w < rhs.w;
}
}edg[N * 2];//因为是无向图,所以边数要乘以2
int find(int a)//并查集找祖宗
{
if(p[a] != a) p[a] = find(p[a]);
return p[a];
}
void klskr()
{
for(int i = 1; i <= m; i++)//依次尝试加入每条边
{
int pa = find(edg[i].a);// a 点所在的集合找祖宗
int pb = find(edg[i].b);// b 点所在的集合找祖宗
if(pa != pb)//如果 a b 不在一个集合中,即祖宗不是同一个
{
res += edg[i].w;//该集合的权重要加上ab之间的权重,不是ab祖宗的权重,因为是把ab的边加入集合
p[pa] = pb;//a的祖宗为b的祖宗,即b的祖宗多一个儿子
cnt ++; // 保留的边数量+1,因为生成了一条边
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) p[i] = i;//初始化并查集
for(int i = 1; i <= m; i++)//读入每条边
{
int a, b , c;
scanf("%d%d%d",&a,&b,&c);
edg[i] = {a, b, c};
}
sort(edg + 1, edg + m + 1);//按边长升序,+1是因为0号位不存元素
klskr();
if(cnt < n - 1)
{//边数最小也是点的数量-1,如果更小,则说明不连通
printf("impossible\n");
return 0;
}
printf("%d\n",res);
return 0;
}