题目
分析
Kruskal算法
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 返回最小的花费代价使得这n户人家连接起来
* @param n int n户人家的村庄
* @param m int m条路
* @param cost int二维数组 一维3个参数,表示连接1个村庄到另外1个村庄的花费的代价
* @return int
*/
//记录每个节点的父节点
public int[] parent;
//记录当前节点的深度
public int[] depth;
public int miniSpanningTree (int n, int m, int[][] cost) {
// write code here
//统计最小花费
int counter = 0;
int num = 0;
this.parent = new int[n + 1];
Arrays.fill(this.parent,-1);
this.depth = new int[n + 1];
//按照花费排列边
PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[2] -o2[2];
}
});
//加入边集
for(int[] o:cost) {
queue.add(o);
}
while(!queue.isEmpty()) {
//弹出当前队列中的最小元素
int[] ele = queue.poll();
//获取两个节点
int x = ele[0];
int y = ele[1];
//判断加入该边是否会构成环
boolean circle = union(x,y);
if(circle == true) {
continue;
}else {//加入该边
num++;
counter+=ele[2];
if(num == n-1) {
return counter;
}
}
}
return 0;
}
//查找节点x的根节点
public int find(int x) {
while (parent[x] != -1) {
x = parent[x];
}
return x;
}
//判断x节点所在集合与y所在集合是否相连,返回结果如果加入(x,y)这条边构成环返回true,否则返回false
public boolean union(int x,int y) {
//如果x和y所在集合的根节点相同,说明其属于同一个集合,而x和y之间有边,说明可以构成环
int r1 = find(x);
int r2 = find(y);
if(r1 == r2) {
return true;
} else {//说明x和y属于不同的集合,此时连接这连个集合
if(depth[r1] == depth[r2]) {
parent[r2] = r1;
depth[r1]++;
} else if(depth[r1] > depth[r2]) {
parent[r2] = r1;
} else {
parent[r1] = r2;
}
}
return false;
}
}