这个是典型的最小生成树问题,可以用最简单的Kruskal 算法解决,这个算法基于贪心的思想,所以实现起来比较简单,Kruskal 算法的思想是先找出所有的边(这一步需要O(n^2))的时间复杂度,然后对所有的边进行排序,O(mlogm),然后我们从小到大枚举所有边,判断这条边对应的两个点是否相连接,如果没有相连,证明这个边就是可以使用的,即让他加入到答案,Kruskal 算法需要搭配并查集使用。
struct Edge {
int len, x, y;
Edge(int len, int x, int y) : len(len), x(x), y(y) {}
};
class Union{
private:
vector<int> p;
int n;
public:
Union(int n){
this->n = n;
p.resize(n);
for(int i=0;i<n;i++) p[i] = i;
}
int find(int x){
if(x!=p[x]) p[x] = find(p[x]);
return p[x];
}
void unite(int x, int y){
p[find(x)] = find(y);
}
bool isUnite(int x, int y){
return find(x) == find(y);
}
};
// 存储边,边的长度,加上两个顶点的编号。
class Solution {
public:
int dis(vector<int> &pointA, vector<int> &pointB){
return abs(pointA[0]-pointB[0])+abs(pointA[1]-pointB[1]);
}
int minCostConnectPoints(vector<vector<int>>& points) {
vector<Edge> edges;
for(int i=0;i<points.size();i++){
for(int j=i+1;j<points.size();j++){
edges.push_back(Edge(dis(points[i],points[j]),i,j));
}
}
sort(edges.begin(),edges.end(),[](Edge &edgeA,Edge &edgeB){return edgeA.len<edgeB.len;});
Union un(points.size());
int res = 0, num = 1;
for (auto& [len, x, y] : edges) {
if(!un.isUnite(x,y)){
res += len;
num++;
un.unite(x,y);
if(num == points.size()){
break;
}
}
}
return res;
}
};