#include<iostream>
#include<memory>
#include<vector>
#include<algorithm>

class UnionFind{
private:
	int n;
	std::unique_ptr<int[]> par, rank;
public:
	UnionFind(int n);
	int find(int x);
	void unite(int x, int y);
	bool same(int x, int y);
};

UnionFind::UnionFind(int _n)
	:n(_n)
{
	this->par.reset(new int[n]);
	this->rank.reset(new int[n]);
	for(int i=0;i<n;i++){
		this->par[i] = i;
		this->rank[i] = 0;
	}
}

int UnionFind::find(int x){
	if(x == this->par[x]){
		return x;
	}
	return this->par[x] = find(par[x]);
}

void UnionFind::unite(int x, int y){
	x = find(x);
	y = find(y);
	if(x == y){//すでに同じ
		return;
	}

	if(rank[x] < rank[y]){
		par[x] = y;
	}else{
		par[y] = x;
		if(rank[x] == rank[y]){
			rank[x]++;
		}
	}
}

bool UnionFind::same(int x, int y){
	return find(x) == find(y);
}

struct Edge{
	int from, to, cost;
};

bool comp(const Edge& l_edge, const Edge& r_edge){
	return l_edge.cost < r_edge.cost;
}

const int MAX_N = 100, MAX_M = 100;
const int INF = 1 << 24;

int kruskal(int V, std::vector<Edge> &ev){
		std::sort(ev.begin(), ev.end(), comp);
		UnionFind uf(V);
		int res = 0, ev_size = ev.size();
		for(int i=0;i<ev_size;i++){
			Edge e = ev[i];
			if(!uf.same(e.from, e.to)){
				uf.unite(e.from, e.to);
				res += e.cost;
			}
		}
		return res;
}

int main(){
	int n, m;
	int cost[MAX_N][MAX_N];
	while(std::cin >> n >> m, n){
		std::vector<Edge> ev;

		for(int i=0;i<MAX_N;i++){
			std::fill(cost[i], cost[i]+MAX_N, INF);
		}

		for(int i=0;i<m;i++){
			int a, b, c;
			std::cin >> a >> b >> c;
			Edge e = {a, b, c};
			ev.push_back(e);
		}

		std::cout << kruskal(n, ev) << std::endl;
	}
}