#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <set>
#include <queue>
using namespace std;

#define loop(i,a,b) for(int i=(a);i<int(b);i++)
#define rep(i,b) loop(i,0,b)

// テ」ツつーテ」ツδゥテ」ツδ陛ァツ板ィテ」ツδ佚」ツδε」ツδ?

typedef int Weight;
struct Edge {
    int src, dst;
    Weight weight;
    Edge(int src, int dst, Weight weight) :
        src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
    return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
        e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

// テヲツ慊?・ツーツ湘・ツ?ィテ・ツ淞淌ヲツ慊ィ(Minimum Spanning Tree) by Prim Algorithm
/*
  g : テ」ツつーテ」ツδゥテ」ツδ?
  r : テヲツ慊?・ツ按敕」ツ?ォテ・ツ青ォテ」ツつ?ゥツ?づァツつケ
*/
pair<Weight, Edges> MST(const Graph &g, int r = 0) {
    int n = g.size(); Edges T; Weight total = 0;
    vector<bool> visited(n);
    priority_queue<Edge> q;
    q.push(Edge(-1, r, 0));
    while (q.size()) {
        Edge e = q.top(); q.pop();
        if (visited[e.dst]) continue;
        T.push_back(e);
        total += e.weight;
        visited[e.dst] = true;
        for(auto& f: g[e.dst]) if (!visited[f.dst]) q.push(f);
    }
    return pair<Weight, Edges>(total, T);
}

int main(){
    int n,m;
    while(cin>>n>>m && n){
        Graph g(n);
        rep(i,m){
            int a,b,c;
            cin>>a>>b>>c;
            g[a].emplace_back(a,b,c);
            g[b].emplace_back(b,a,c);
        }
        cout << MST(g).first << endl;
    }
}