题目描述:
输入
第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000)
第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)
输出
输出最小生成树的所有边的权值之和。
输入示例
9 14
1 2 4
2 3 8
3 4 7
4 5 9
5 6 10
6 7 2
7 8 1
8 9 7
2 8 11
3 9 2
7 9 6
3 6 4
4 6 14
1 8 8
输出示例
37
import java.util.Arrays;
import java.util.Scanner;
public class Kruskal {
public static void kruskal(Node[] nodes, int[] parent, int[] ans, int M) {
long res = 0;
for (int i = 0; i < M; i++) {
int u = nodes[i].u;
int v = nodes[i].v;
if (find(u, parent) != find(v, parent)) { //u和v不在一个集合
res += nodes[i].w;
merge(u,v,parent,ans);
}
}
System.out.println(res);
}
public static int find(int i, int[] parent) {
int tmp;
//查找位置
for (tmp = i; parent[tmp] != tmp; tmp = parent[tmp]);
//路径压缩
while (tmp != i) {
int t = parent[i];
parent[i] = tmp;
i = t;
}
return tmp;
}
public static void merge(int a, int b, int[] parent, int[] ans) {
int r1 = find(a, parent);
int r2 = find(b, parent);
int tmp = ans[r1] + ans[r2];
if (ans[r1] < ans[r2]) {
parent[r1] = r2;
ans[r2] = tmp;
} else {
parent[r2] = r1;
ans[r1] = tmp;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = scanner.nextInt();
int M = scanner.nextInt();
Node[] nodes = new Node[M + 5];
int[] parent = new int[N + 5];
int[] ans = new int[N + 5];
for (int i = 1; i <= N; i++) {
parent[i] = i;
ans[i] = 1;
}
for (int i = 0; i < M; i++) {
nodes[i] = new Node(scanner.nextInt(), scanner.nextInt(), scanner.nextInt());
}
Arrays.sort(nodes, 0, M, (o1, o2) -> o1.w - o2.w);
kruskal(nodes, parent, ans, M);
}
}
class Node {
int u;
int v;
int w;
public Node(int u, int v, int w) {
this.u = u;
this.v = v;
this.w = w;
}
public Node() {
}
}