#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e5+10;
struct node
{
int u,v,w;
}e[2*maxn];
int fa[maxn]; // fa[i] 为顶点 i 所在集合对应的树中的根结点
int r[maxn];
int n,m; //点和边
void init() //初始化
{
for(int i=0;i<=n;i++)
{
fa[i] = i;
r[i] = 0;
}
}
bool cmp(node a,node b)
{
return a.w<b.w;
}
int find(int x)
{
/*int s = x;
while(s!=fa[s])
s = fa[s]
while(s!=x)
{
int temp = fa[x];
fa[x] = s;
x = temp;
}
return s;*/
if(fa[x]==x)
return x;
else
return fa[x] = find(fa[x]);
}
void merge(int x,int y)
{
x = find(x), y = find(y);
if(x!=y)
{
if( r[x]<r[y] )
fa[x] = y;
else
{
fa[y] = x;
if( r[x]==r[y] )
r[x]++;
}
}
}
void kruskal()
{
int sumw = 0; //生成树的权值
int num = 0; //已选用边的数目
int u,v;
init();
for(int i=0; i<m; i++)
{
u = e[i].u;
v = e[i].v;
if( find(u)!=find(v) )
{
//printf("%d %d %d\n",u,v,e[i].w);
sumw += e[i].w;
num++;
merge(u,v);
}
if(num >= n-1)
break;
}
printf("%d\n",sumw);
}
int main()
{
int t;
int u,v,w;
while(~scanf("%d",&n) && n)
{
scanf("%d",&m);
for(int i=0; i<m ;i++)
{
scanf("%d%d%d",&u,&v,&w);
e[i].u = u;
e[i].v = v;
e[i].w = w;
}
sort(e,e+m,cmp);
kruskal();
}
return 0;
}