题目如下:
给你一个
points
数组,表示 2D 平面上的一些点,其中points[i] = [xi, yi]
。连接点
[xi, yi]
和点[xj, yj]
的费用为它们之间的 曼哈顿距离 :|xi - xj| + |yi - yj|
,其中|val|
表示val
的绝对值。请你返回将所有点连接的最小总费用。只有任意两点之间 有且仅有 一条简单路径时,才认为所有点都已连接。
思路:
1.首先快速构建一下图结构:记结构体edge内含m,n,w三个整数,其中m,n为点序号,w为以m,n两点构成的边的权重(即曼哈顿距离),顺便把求解曼哈顿距离的函数写了:
struct edge{
int m,n,w;
edge(int iptm,int iptn,int iptw){
m=iptm;n=iptn;w=iptw;
}
};
int Manhattan(vector<int> A,vector<int> B){
return (abs(A[0]-B[0])+abs(A[1]-B[1]));
}
2.构建并查集:设置一个哈希映射全局变量,并利用路径压缩实现查找父亲操作:
unordered_map<int,int> fa;
int find(int x){
if(x==fa[x]){
return x;
}
else{
fa[x]=find(fa[x]);
return fa[x];
}
}
3.构建最小生成树算法:这里选用Kruskal算法:先将边按权重w从小到大排序,然后依次选取:如果选取的边的m,n两点父亲不同,则选中这条边,并将点m的父亲设置为点n的父亲实现合并操作,确保了不形成环。图解:
for(int i=0;i<edges.size();i++){
if(find(edges[i].m)!=find(edges[i].n)){
fa[find(edges[i].m)] = find(fa[edges[i].n]);
minCost = minCost + edges[i].w;
}
}
完整代码如下:
class Solution {
public:
struct edge{
int m,n,w;
edge(int iptm,int iptn,int iptw){
m=iptm;n=iptn;w=iptw;
}
};
unordered_map<int,int> fa;
int minCost=0;
int find(int x){
if(x==fa[x]){
return x;
}
else{
fa[x]=find(fa[x]);
return fa[x];
}
}
int Manhattan(vector<int> A,vector<int> B){
return (abs(A[0]-B[0])+abs(A[1]-B[1]));
}
int minCostConnectPoints(vector<vector<int>>& points) {
int total = points.size();
vector<edge> edges;
int index=0;
for(int i=0;i<total;i++){
for(int j=i+1;j<total;j++){
edges.push_back(edge(i,j,Manhattan(points[i],points[j])));
}
}
sort(edges.begin(),edges.end(),[](edge a,edge b)
{return a.w < b.w;}
);
for(int i=0;i<total;i++){
fa[i]=i;
}
for(int i=0;i<edges.size();i++){
if(find(edges[i].m)!=find(edges[i].n)){
fa[find(edges[i].m)] = find(fa[edges[i].n]);
minCost = minCost + edges[i].w;
}
}
return minCost;
}
};
感谢你能看到这里。