Problem:
橋の取り壊し

水の国ウォーターデブンには n 個の都市があります。各都市は水に囲まれており、島国のようになっています。ウォーターデブンには m 本の橋があり、都市間の交通はそれらの橋によって行われ、全ての都市に行き来することができます。

最近、道路特定財源の見直しにより橋の維持費の削減が決定されました。全部の橋を維持することができなくなってしまい、いくつかの橋を取り壊すことになりました。そこで、ウォーターデブンはどの都市にでも行くことができるように橋を残しつつ、橋の維持費を最小化することが課題となりました。

都市の数、橋の数、各橋の維持費を入力とし、橋を利用してどの都市にも行けるようにしつつ、橋を取り壊した場合の維持費の最小値を出力するプログラムを作成してください。なお、橋の取り壊しには費用が掛からないものとします。ただし、各都市は 0 から n - 1 まで順番に番号が付けられているものとします。

Input

複数のデータセットの並びが入力として与えられます。入力の終わりはゼロふたつの行で示されます。各データセットは以下の形式で与えられます。

n m
a1 b1 cost1
a2 b2 cost2
:
am bm costm

１行目に都市の数 n (2 ≤ n ≤ 100)、 橋の数 m (1 ≤ m ≤ 500) が与えられます。続く m 行に第 i の橋の情報が与えられます。ai, bi は橋がつないでいる都市の番号、costi (1 ≤ costi ≤ 1000) は橋にかかる維持費を表します。

Output

データセット毎に橋の維持費の合計を１行に出力します。

Sample Input

5 6
0 2 1
2 1 3
2 3 8
1 3 2
3 4 5
1 4 4
3 3
1 2 3
2 0 3
0 1 3
0 0

Output for the Sample Input

10
6

Solution in JAVA (judge verdict: Accepted)

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		Scanner scan = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		while(true){
			short n=scan.nextShort(),m=scan.nextShort();
			if(n==0) break;
			UnionFind uni = new UnionFind(n);
			List<edge> list = new ArrayList<edge>();
			for (int i = 0; i < m; i++)
				list.add(new edge(scan.nextShort(),scan.nextShort(),scan.nextShort()));
			Collections.sort(list);

			int res=0;
			for (int i = 0; i < m; i++) {
				edge e = list.get(i);
				if(!uni.isSame(e.from,e.to)){
					uni.unite(e.from, e.to);
					res+=e.cost;
				}
			}
			out.println(res);
		}
		out.flush();
	}
}

class edge implements Comparable<Object> {
	short from,to,cost;
	edge(short f,short t,short c){
		from=f;
		to=t;
		cost=c;
	}
	@Override
	public int compareTo(Object o) {
		return this.cost-((edge)o).cost;
	}
}

class UnionFind {

	int[] par,rank;

	UnionFind(int n){
		par = new int[n];
		rank = new int[n];
		for(int i=0;i<n;i++){
			par[i]=i;
			rank[i]=0;
		}
	}

	int root(int x){
		if(par[x]==x)
			return x;
		else
			return par[x] = root(par[x]);
	}

	void unite(int x,int y){
		x=root(x);
		y=root(y);
		if(x==y) return;

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

	boolean isSame(int x,int y){
		return root(x)==root(y);
	}
}