链接:https://leetcode-cn.com/problems/min-cost-to-connect-all-points/
给你一个points
数组,表示 2D 平面上的一些点,其中 points[i] = [xi, yi]
。
连接点 [xi, yi]
和点 [xj, yj]
的费用为它们之间的 曼哈顿距离 :|xi - xj| + |yi - yj|
,其中 |val|
表示 val
的绝对值。
请你返回将所有点连接的最小总费用。只有任意两点之间 有且仅有 一条简单路径时,才认为所有点都已连接。
示例 1:
输入:points = [[0,0],[2,2],[3,10],[5,2],[7,0]]
输出:20
解释:
我们可以按照上图所示连接所有点得到最小总费用,总费用为 20 。
注意到任意两个点之间只有唯一一条路径互相到达。
示例 2:
输入:points = [[3,12],[-2,5],[-4,1]]
输出:18
示例 3:
输入:points = [[0,0],[1,1],[1,0],[-1,1]]
输出:4
示例 4:
输入:points = [[-1000000,-1000000],[1000000,1000000]]
输出:4000000
示例 5:
输入:points = [[0,0]]
输出:0
提示:
1 <= points.length <= 1000
-106 <= xi, yi <= 106
- 所有点
(xi, yi)
两两不同。
思路:题目要求任意两点之间只有一条简单路径,即不存在环路。实际上本题就是在考查有边权的情况下如何构建一个最小树,自然想到使用kruskal算法。
class Solution {
public:
struct Edge{
int u, v, w;
bool operator < (const Edge edge) const {
return w < edge.w;
}
};
Edge edges[1000010];
int Father[1010];
int Find(int x){
return x == Father[x] ? x : Father[x] = Find(Father[x]);
}
bool Union(int A,int B){
A = Find(A);
B = Find(B);
if(A == B) return false;
Father[A] = B;
return true;
}
int minCostConnectPoints(vector<vector<int>>& points) {
int n = points.size(), i, j, cnt = 0, cost = 0;
for(i = 0; i < n; ++ i){
Father[i] = i;
for(j = i + 1; j < n; ++ j){
edges[cnt ++] = Edge{i, j, abs(points[i][0] - points[j][0])+abs(points[i][1] - points[j][1])};
}
}
sort(edges, edges + cnt);
-- n;
for(i = 0; i < cnt; ++ i){
if(!n) break; //已经构建了n-1条边
if(Union(edges[i].u, edges[i].v)){
-- n;
cost += edges[i].w;
}
}
return cost;
}
};