/*prime模板,时间复杂度o(v^2)*/
#include <cstdio>
#include <cstring>
#define N 1005
#define INF 0x3f3f3f3f
int map[N][N], dis[N], vis[N];
int n, m;
int cnt = 0, sum = 0;
void init()
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (i == j) map[i][j] = 0;
else map[i][j] = INF;
}
}
return;
}
void creatgraph()
{
int i, j, w;
for (int k = 0; k < m; k++)
{
scanf("%d%d%d", &i, &j, &w);
if (map[i][j] > w)//重边取最小
map[i][j] = map[j][i] = w;//无向图
}
return;
}
int prime(int start)
{
for (int i = 1; i <= n; i++)//dis存储节点1到其他各个节点的距离,达不到用INF表示
dis[i] = map[start][i];
cnt++;
memset(vis, 0, sizeof(vis));
vis[start] = 1;//记下第一个节点
while (cnt < n)
{
int min = INF, j = -1;
for (int i = 1; i <= n; i++)//找当前生成树加一个节点所需的最小权值min,并记录该节点
{
if (!vis[i] && dis[i] < min)
{
min = dis[i];
j = i;
}
}
if (min == INF) return -1;//图不连通
vis[j] = 1; cnt++; sum += min;//标记新节点,累加最小权值
/*下边更新dis数组,根据新节点到各个未知节点的距离来更新*/
for (int k = 1; k <= n; k++)
{
if (!vis[k] && dis[k] > map[j][k])
dis[k] = map[j][k];
}
}
return sum;
}
int main()
{
while (scanf("%d%d", &n, &m) != EOF)//输入顶点数和边数
{
int ans = 0;
cnt = 0; sum = 0;//cnt表示生成树的顶点个数,sum存储路径和
init();//初始化图
creatgraph();//建图
int start;
//scanf("%d", &start);
ans = prime(1);//核心算法
if (ans != -1)
printf("%d\n", ans);
else
printf("图不连通,最小生成树不存在\n");
}
return 0;
}