测试输入包含若干测试用例。每个测试用例的第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); } } }