先用1012题的思路,判断是否有能连通。用图的邻接矩阵,prime算法求BST
代码:
package Test1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class Test37_1024 {
/**
* by qr jobdu 1024 2014-8-19
*
* @throws IOException
*/
public static void main(String[] args) throws IOException {
StreamTokenizer st = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
int n, m;
while (true) {
st.nextToken();
n = (int) st.nval; // 道路数目
st.nextToken();
m = (int) st.nval; // 村庄数目
if (n == 0)
break;
int arr[][] = new int[m + 1][m + 1]; // 无穷(用很大的数代替)代表没有路,非0代表有路
for (int i = 0; i <= m; i++)
for (int j = 0; j <= m; j++) {
arr[i][j] = Integer.MAX_VALUE;
}
UnionFindSet ufs = new UnionFindSet(m + 1);
// 延续1012题的思路,先判断是否可以实现相通
int n1, n2, weight, num = 0;
for (int i = 0; i < n; i++) {
st.nextToken();
n1 = (int) st.nval;
st.nextToken();
n2 = (int) st.nval;
st.nextToken();
weight = (int) st.nval;
// 去重复边??
if (arr[n1][n2] == 0) {
arr[n1][n2] = weight;
arr[n2][n1] = weight;
} else {
arr[n1][n2] = Math.min(arr[n1][n2], weight);
arr[n2][n1] = Math.min(arr[n1][n2], weight);
}
if (ufs.find(n1) != ufs.find(n2)) {
ufs.union(n1, n2);
num++;
}
}
if (num >= (m - 1)) { // 可以相通,求BST(prim)
int flag[] = new int[m + 1];// 0代表该顶点不在集合U中,1代表在集合U中
flag[1] = 1; // 从顶点1开始
int pos = 1; // 目前的顶点
int numedge = 0; // 代表加入TE中的边的个数
int wei = 0; // BST的权重之和
int min[] = new int[m + 1]; // 边的权重
for (int i = 1; i <= m; i++) {
min[i] = arr[pos][i];
}
while (true) {
int minmin = Integer.MAX_VALUE;
int lastpos=pos;
for (int i = 1; i <= m; i++) {
if (flag[i] == 0 && min[i] < minmin) {
minmin = min[i];
lastpos=pos;
pos = i;
}
}
flag[pos] = 1;
for (int i = 1; i <= m; i++) {
if (flag[i] == 0 && min[i] > arr[pos][i])
min[i] = arr[pos][i];
}
// wei += arr[lastpos][pos];
wei+=min[pos];//!!!!
numedge++; // 名字一定要区分开使用范围,不然容易出错
if (numedge == (m - 1))
break;
}
System.out.println(wei);
} else { // 不能相通
System.out.println("?");
}
}
}
}
class UnionFindSet {
int set[];
int size[];
UnionFindSet() {
}
UnionFindSet(int n) {
set = new int[n];
size = new int[n];
for (int i = 0; i < n; i++) {
set[i] = i;
size[i] = 1;
}
}
int find(int i) {
while (i != set[i]) {
i = set[i];
}
return i;
}
void union(int i, int j) {
int p = find(i);
int q = find(j);
if (size[p] < size[q]) {
set[p] = q;
size[q] += size[p]; // 勿忘修改size
} else {
set[q] = p;
size[p] += size[q];
}
}
}