题目
https://leetcode-cn.com/problems/min-cost-to-connect-all-points/
Kruscal算法
最小生成树:
图的生成树是他的一棵含有所有顶点的无环连通子图。一幅加权图的最小生成树(MST)
是它的一棵权值最小的生成树。
题目可以转换为求最小生成树的权值总和
Kruscal算法流程:
- 将图 G = { V , E } G = \{V, E\} G={V,E} 中所有的边按照从小到达排序,等长的边任意排序
- 初始化图 G ′ 为 { V , 、 ∅ } G'为 \{V, 、\varnothing\} G′为{V,、∅}从前往后扫描排序后的边,如果边 e e e连接了两个不同的连通分量则将该边加入图 G ′ G' G′中。
- 最后得到的图 G ′ G' G′就是图 G G G的最小生成树
使用并查集维护连通性,若当前边两端不连通即可选择这条边。
class Solution {
public int minCostConnectPoints(int[][] points) {
int n = points.length;// 顶点数量
UnionFind uf = new UnionFind(n);
List<Edge> edges = new ArrayList<>();
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
edges.add(new Edge(distance(points, i, j), i, j));
}
}
Collections.sort(edges, (o1, o2) -> o1.len - o2.len);
int res = 0, num = 1;
for (Edge edge : edges) {
int len = edge.len, x = edge.x, y = edge.y;
if (!uf.isConnected(x, y)) {
res += len;
num++;
uf.union(x, y);
if (num == n) break;
}
}
return res;
}
private int distance(int[][] points, int x, int y) {
return Math.abs(points[x][0] - points[y][0]) + Math.abs(points[x][1] - points[y][1]);
}
class UnionFind {
private int[] parent;
private int[] rank;
public UnionFind(int n) {
parent = new int[n];
rank = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
rank[i] = 1;
}
}
public int find(int x) {
if (x != parent[x]) {
parent[x] = find(parent[x]);
}
return parent[x];
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY)
return;
if (rank[rootX] == rank[rootY]) {
parent[rootX] = rootY;
rank[rootY] += 1;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
parent[rootY] = rootX;
}
}
public boolean isConnected(int x, int y) {
return find(x) == find(y);
}
}
class Edge {
int len, x, y;
public Edge(int len, int x, int y) {
this.len = len;
this.x = x;
this.y = y;
}
}
}