测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M (N, M < =100 );随后的 N 行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2 0 100
3 ?
import java.util.Arrays;
import java.util.Scanner;
public class Main {
//并查集+Kruskal算法
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
if (n == 0) break;
int m = scanner.nextInt();
UnionFind unionFind = new UnionFind(m + 1);
Path[] paths = new Path[n];
for (int i = 0; i < n; i++) paths[i] = new Path(scanner.nextInt(), scanner.nextInt(), scanner.nextInt());
Arrays.sort(paths);
int sum = 0;
for (Path path : paths) {
if (unionFind.count > 2) {
if (unionFind.find(path.a)!=unionFind.find(path.b)){
unionFind.union(path.a, path.b);
sum += path.cost;
}
} else break;
}
System.out.println(unionFind.count==2?sum:"?");
}
}
public static class UnionFind {
private int[] id;
public int count;
public UnionFind(int N) {
count = N;
id = new int[N];
for (int i = 0; i < N; i++) id[i] = i;
}
public int find(int p) {
return id[p];
}
public void union(int p, int q) {
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) return;
for (int i = 0; i < id.length; i++)
if (id[i] == pRoot) id[i] = qRoot;
count--;
}
}
static class Path implements Comparable<Path> {
Integer a;
Integer b;
Integer cost;
public Path(Integer a, Integer b, Integer cost) {
this.a = a;
this.b = b;
this.cost = cost;
}
@Override
public int compareTo(Path o) {
return this.cost.compareTo(o.cost);
}
}
}