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

using namespace std;

class Edge {
public:
    int u, v, cost;
    Edge() {}
    Edge(int _u, int _v, int _cost) {
        u = _u;
        v = _v;
        cost = _cost;
    }

    bool operator<(const Edge& e) const {
        return cost < e.cost;
    }
};

class UnionFind {
public:
    int n;
    vector<int> parent_nodes, rank;
    UnionFind() {}
    UnionFind(int _n) {
        n = _n;
        // all node is same rank
        for (int i = 0; i < n; ++i) {
            parent_nodes.push_back(i);
            rank.push_back(0);
        }
    }

    int find(int v) {
        if(parent_nodes[v] == v) return v; // return root.
        return parent_nodes[v] = find(parent_nodes[v]); // compress path
    }

    // unite sets
    void unite(int x, int y) {
        x = find(x);
        y = find(y);

        if (x == y){
            return;
        }

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

        return;
    }

    // validation of same set
    bool same(int x, int y) {
        return find(x) == find(y);
    }
};

int kruskal(int n_vertex, int n_edge, vector<Edge> edges) {
    int costs = 0;
    sort(edges.begin(), edges.end());
    UnionFind uf = UnionFind(n_vertex);

    for (int i = 0; i < n_edge; ++i) {
        if(!uf.same(edges[i].u, edges[i].v)) {
            uf.unite(edges[i].u, edges[i].v);
            costs += edges[i].cost;
        }
    }

    return costs;
}


int main()
{
    int n, m, a, b, cost, result;
    vector<Edge> edges;
    while(cin>>n>>m) {
        if(n == 0 && m == 0) {
            break;
        }
        for (int i = 0; i < m; ++i) {
            cin >> a >> b >> cost;
            edges.push_back(Edge(a, b, cost));
        }

        result = kruskal(n, m, edges);
        cout << result << endl;
        edges.clear();
    }
    return 0;
}