Leetcode 1584. 连接所有点的最小费用
题目:
给你一个 p o i n t s points points 数组,表示 2 D 2D 2D 平面上的一些点,其中 p o i n t s [ i ] = [ x i , y i ] points[i] = [xi, yi] points[i]=[xi,yi]。
连接点 [ x i , y i ] [xi, yi] [xi,yi]和点 [ x j , y j ] [xj, yj] [xj,yj]的费用为它们之间的 曼哈顿距离 : ∣ x i − x j ∣ + ∣ y i − y j ∣ |xi - xj| + |yi - yj| ∣xi−xj∣+∣yi−yj∣,其中 ∣ v a l ∣ |val| ∣val∣ 表示 v a l 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
<
=
p
o
i
n
t
s
.
l
e
n
g
t
h
<
=
1000
1 <= points.length <= 1000
1<=points.length<=1000
−
1
0
6
<
=
x
i
,
y
i
<
=
1
0
6
-10^6 <= xi, yi <= 10^6
−106<=xi,yi<=106
所有点$ (xi, yi)$ 两两不同。
思路:
枚举所有的边,按长从小到大排序
并查集判断两个点之间有没有连接
如果一条边直接的两个点没有连接,那么这条边一定是他们之间最短的距离
再把两条边连接上,每次连接加上距离即可
代码:
class Solution {
public:
struct A {
int val, tval;//两个点编号
int distance;//两个点距离
} road[500000];
int f[1010];
int fa(int n) {
if (f[n] == n) return n;
return f[n] = fa(f[n]);
}
void connect(int x, int y) {
int fx = fa(x);
int fy = fa(y);
if (fx > fy) {
f[fy] = fx;
} else {
f[fx] = fy;
}
}
static bool is(struct A a, struct A b) {
return a.distance < b.distance;
}
int minCostConnectPoints(vector <vector<int>> &points) {
int len = points.size();//点的数量
for (int i = 0; i <= len; i++) f[i] = i;
int n = 0;//边的数量
//枚举所有边
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
road[n].val = i;
road[n].tval = j;
road[n].distance = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]);
n++;
}
}
sort(road, road + n, is);//按边的长度从小到大排序
int val = 0;
for (int i = 0; i < n; i++) {
//如果一条边的两个点的父节点不一样说明两个点之间没有连接
if (fa(road[i].val) != fa(road[i].tval)) {
val += road[i].distance;
connect(road[i].val, road[i].tval);
}
}
return val;
}
};