题目描述
Farmer John 的农场缺水了。
他决定将水引入到他的 n n n 个农场。他准备通过挖若干井,并在各块田中修筑水道来连通各块田地以供水。在第 i i i 号田中挖一口井需要花费 W i W_i Wi 元。连接 i i i 号田与 j j j 号田需要 P i , j P_{i,j} Pi,j( P j , i = P i , j P_{j,i}=P_{i,j} Pj,i=Pi,j)元。
请求出 FJ 需要为使所有农场都与有水的农场相连或拥有水井所需要的最少钱数。
输入格式
第一行为一个整数 n n n。
接下来 n n n 行,每行一个整数 W i W_i Wi。
接下来 n n n 行,每行 n n n 个整数,第 i i i 行的第 j j j 个数表示连接 i i i 号田和 j j j 号田需要的费用 P i , j P_{i,j} Pi,j。
输出格式
输出最小开销。
样例 #1
样例输入 #1
4
5
4
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
样例输出 #1
9
提示
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 300 1 \leq n \leq 300 1≤n≤300, 1 ≤ W i ≤ 1 0 5 1 \leq W_i \leq 10^5 1≤Wi≤105, 0 ≤ P i , j ≤ 1 0 5 0 \leq P_{i,j} \leq 10^5 0≤Pi,j≤105。
需要考虑地下的源点,连接地上的田,田之间水道相互连接
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static Node[] a = new Node[2000005];
public static int[] fa = new int[1005];
public static int k = 0;
//初始化
public static void init(int x) {
for (int i = 0; i < x; i++) {
fa[i] = i;
}
}
//查询
public static int find(int x) {
if (fa[x] == x) {
return x;
} else {
fa[x] = find(fa[x]);
return fa[x];
}
}
//合并
public static void union(int x, int y) {
int find_x = find(x);
int find_y = find(y);
fa[find_x] = find_y;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int z;
init(1005);
for (int i = 1; i <= n; i++) {
z = scanner.nextInt();
a[k] = new Node();
a[k].x = 0;
a[k].y = i;
a[k].z = z;
k++;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
z = scanner.nextInt();
if (j > i) {
a[k] = new Node();
a[k].x = i;
a[k].y = j;
a[k].z = z;
k++;
}
}
}
Arrays.sort(a, 0, k, (o1, o2) -> {
return o1.z - o2.z;
});
long ans = 0;
for (int i = 0; i < k; i++) {
if (find(a[i].x) != find(a[i].y)) {
union(a[i].x, a[i].y);
ans += a[i].z;
}
}
System.out.println(ans);
}
}
class Node {
int x;
int y;
int z;
}