/*
Kruskal 算法思路
1. 把所有边按权值从小到大排序O(mlogm)
2. for 所有边 a, b, w O(m)
if a, b不连通
将这条边加入集合中
*/
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 200010;
int n, m;
int p[N];
struct Edge
{
int a, b, w;
bool operator < (const Edge& t) const
{
return w < t.w;
}
}edges[N];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
cin >> n >> m;
for (int i = 0; i < m; i ++ )
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
edges[i] = {a, b, w};//下面思考一下重边和自环
}
sort(edges, edges + m);//按权值从小到大排序,重边这里加上判断a!=b过滤掉
for (int i = 1; i <= n; i ++ ) p[i] = i;
int res = 0, cnt = 0;//res存储所有边的权值之和,cnt存的是边数
for (int i = 0; i < m; i ++ )
{
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a = find(a), b = find(b);//如果是自环或回环路的话,a!=b过滤掉
if (a != b)//a, b不连通
{
p[a] = b;//连通
res += w;
cnt ++ ;
}
}
//重边,自环, 回环路都过滤掉了,边数就应该是n - 1 条,没有这么多条,正面最小生成树不存在,写小于< 是代码少点
if (cnt < n - 1) puts("impossible");
else printf("%d\n", res);
return 0;
}