#include <iostream>
#include <complex>
#include <sstream>
#include <string>
#include <algorithm>
#include <deque>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <vector>
#include <set>
#include <limits>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
#define REP(i, j) for(int i = 0; i < (int)(j); ++i)
#define FOR(i, j, k) for(int i = (int)(j); i < (int)(k); ++i)
#define SORT(v) sort((v).begin(), (v).end())
#define REVERSE(v) reverse((v).begin(), (v).end())
typedef complex<double> P;

vector<int> v, parent, depth;

int find(int a){
  if(parent[a] == a) return a;
  else return parent[a] = find(parent[a]);
}

void merge(int a, int b){
  int pa = find(a), pb = find(b);
  if(pa == pb) return ;

  if(depth[pa] > depth[pb]) swap(pa, pb);
  if(depth[pa] == depth[pb]) ++depth[pa];
  parent[pb] = pa;
}

bool same(int a, int b){
  return find(a) == find(b);
}

void init_union_find(int V){
  v = vector<int>(V);
  parent = vector<int>(V);
  depth = vector<int>(V, 1);
  REP(i, V) parent[i] = i;
}

struct edge {
  int f, t, c;
  bool operator < (const edge &e) const { return c < e.c; };
};

int kruskal(int V, int E, vector<edge> es){
  sort(es.begin(), es.end());
  init_union_find(V);
  int min_cost = 0;
  REP(i, E){
    if(!same(es[i].f, es[i].t)){
      min_cost += es[i].c;
      merge(es[i].f, es[i].t);
    }
  }
  return min_cost;
}

int main() {
  int V, E;
  while(cin >>V >>E && V){
    vector<edge> es(E);
    REP(i, E) cin >>es[i].f >>es[i].t >>es[i].c;
    cout <<kruskal(V, E, es) <<endl;
  }
  return 0;
}