1584.连接所有点的最小费用
思路:
无向完全图的最小生成树问题。
每个坐标点表示一个顶点,遍历顶点找出所有的边,同时计算每条边的权重,存储在优先队列中,方便后面找到最小权重边。这里使用的是克鲁斯卡尔算法寻找最小生成树。
AC代码(Java)
class Solution {
public int minCostConnectPoints(int[][] points) {
List<Node> nodes=new ArrayList<>();// 顶点集合
int len=points.length;
int[] parent=new int[len];
//初始化顶点集合
for(int i=0;i<len;i++){
int x=points[i][0];
int y=points[i][1];
nodes.add(new Node(x,y,i));
parent[i]=i;
}
// 边集合,用优先队列存储
PriorityQueue<Edge> edges = new PriorityQueue<>(new Comparator<Edge>() {
@Override
public int compare(Edge a, Edge b) {
return a.cost-b.cost;
}
});
// 初始化边集合
for(int i=0;i<len;i++){
for(int j=i+1;j<len;j++){
edges.add(new Edge(nodes.get(i),nodes.get(j)));
}
}
// 克鲁斯卡尔算法寻找最小生成树(并查集)
int count = 0;// 统计已经加入最小生成树的边数,最小生成树一共只需要len-1条边
int res = 0;
while (count < len - 1) {
Edge lest = edges.poll();
if(union(parent, lest.v.index, lest.w.index)){
res+=lest.cost;
count++;
}
}
return res;
}
int find(int[] parent,int a){
if(parent[a]!=a){
parent[a]=find(parent,parent[a]);
}
return parent[a];
}
boolean union(int[] parent, int a, int b) {
int roota = find(parent, a);
int rootb = find(parent, b);
if (roota != rootb) {
parent[roota] = rootb;
return true;
}
return false;
}
class Edge{
private int cost;
private Node v;
private Node w;
Edge(Node v,Node w){
this.v=v;
this.w=w;
this.cost=Math.abs(v.x-w.x)+Math.abs(v.y-w.y);
}
}
class Node{
private int x;
private int y;
private int index;
Node(int x,int y,int index){
this.x=x;
this.y=y;
this.index=index;
}
}
}