当前位置: 首页 > news >正文

⭐算法OJ⭐连接所有点的最小费用【最小生成树】(C++实现)Min Cost to Connect All Points

文章目录

  • 问题描述
  • 解题思路
    • 方法1:Kruskal算法(推荐)
      • 代码实现(Kruskal + Union-Find)
      • 复杂度分析
    • 方法2:Prim算法
      • 代码实现(Prim算法)
      • 复杂度分析

1584. Min Cost to Connect All Points
You are given an array points representing integer coordinates of some points on a 2D-plane, where points[i] = [xi, yi].

The cost of connecting two points [xi, yi] and [xj, yj] is the manhattan distance between them: |xi - xj| + |yi - yj|, where |val| denotes the absolute value of val.

Return the minimum cost to make all points connected. All points are connected if there is exactly one simple path between any two points.

问题描述

给定一组二维平面上的点,其中 points[i] = [xi, yi]。连接两点 [xi, yi][xj, yj] 的费用是它们之间的曼哈顿距离:|xi - xj| + |yi - yj|。返回连接所有点所需的最小总费用。所有点都应该被连接,并且任意两点之间有且只有一条路径。

Example 1:
在这里插入图片描述

Input: points = [[0,0],[2,2],[3,10],[5,2],[7,0]]
Output: 20

Explanation:

We can connect the points as shown above to get the minimum cost of 20.
Notice that there is a unique path between every pair of points.
在这里插入图片描述

Example 2:

Input: points = [[3,12],[-2,5],[-4,1]]
Output: 18

解题思路

这是一个典型的**最小生成树(MST)**问题,可以使用 Kruskal算法 或 Prim算法 解决。

方法1:Kruskal算法(推荐)

  • 计算所有边:生成所有可能的点对,并计算它们的曼哈顿距离。
  • 按权重排序边:从小到大排序所有边。
  • 使用并查集(Union-Find):
    • 初始化每个点为一个独立的集合。
    • 遍历排序后的边,如果两个点不在同一集合,就合并它们,并累加费用。
    • 直到所有点连通(即边的数量 = n-1,其中 n 是点的数量)。

代码实现(Kruskal + Union-Find)

#include <vector>
#include <algorithm>
using namespace std;

class UnionFind {
private:
    vector<int> parent;
    vector<int> rank;
public:
    UnionFind(int n) {
        parent.resize(n);
        rank.resize(n, 0);
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }

    int find(int u) {
        if (parent[u] != u) {
            parent[u] = find(parent[u]); // Path compression
        }
        return parent[u];
    }

    bool unionSets(int u, int v) {
        int rootU = find(u);
        int rootV = find(v);
        if (rootU == rootV) return false; // Already connected
        if (rank[rootU] > rank[rootV]) {
            parent[rootV] = rootU;
        } else if (rank[rootU] < rank[rootV]) {
            parent[rootU] = rootV;
        } else {
            parent[rootV] = rootU;
            rank[rootU]++;
        }
        return true;
    }
};

class Solution {
public:
    int minCostConnectPoints(vector<vector<int>>& points) {
        int n = points.size();
        vector<vector<int>> edges; // {cost, u, v}
        
        // Generate all possible edges
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]);
                edges.push_back({cost, i, j});
            }
        }
        
        // Sort edges by cost
        sort(edges.begin(), edges.end());
        
        UnionFind uf(n);
        int res = 0;
        int edgesUsed = 0;
        
        for (auto& edge : edges) {
            int cost = edge[0], u = edge[1], v = edge[2];
            if (uf.unionSets(u, v)) {
                res += cost;
                edgesUsed++;
                if (edgesUsed == n - 1) break;
            }
        }
        
        return res;
    }
};

复杂度分析

  • 时间复杂度: O ( n ² l o g n ) O(n^² log n) O(n²logn)(排序边)。
  • 空间复杂度: O ( n ² ) O(n^²) O(n²)(存储所有边)。

方法2:Prim算法

  • 初始化优先队列(最小堆):从任意一个点开始,将其所有邻边加入堆。
  • 逐步扩展MST:
    • 每次取出权重最小的边,如果该边连接的点未被访问,则加入MST,并累加费用。
    • 将该点的所有邻边加入堆。
  • 直到所有点都被访问。

代码实现(Prim算法)

#include <vector>
#include <queue>
#include <climits>
using namespace std;

class Solution {
public:
    int minCostConnectPoints(vector<vector<int>>& points) {
        int n = points.size();
        vector<bool> visited(n, false);
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> minHeap;
        
        // Start with node 0
        minHeap.push({0, 0});
        
        int res = 0;
        int edgesUsed = 0;
        
        while (edgesUsed < n) {
            auto [cost, u] = minHeap.top();
            minHeap.pop();
            
            if (visited[u]) continue;
            
            visited[u] = true;
            res += cost;
            edgesUsed++;
            
            // Add all edges from u to unvisited nodes
            for (int v = 0; v < n; v++) {
                if (!visited[v]) {
                    int newCost = abs(points[u][0] - points[v][0]) + abs(points[u][1] - points[v][1]);
                    minHeap.push({newCost, v});
                }
            }
        }
        
        return res;
    }
};

复杂度分析

  • 时间复杂度: O ( n ² l o g n ) O(n^² log n) O(n²logn)(优先队列操作)。
  • 空间复杂度: O ( n ) O(n) O(n)(存储 visited 和优先队列)。

相关文章:

  • 申报视频材料要求!第三批南充西充县非物质文化遗产代表性项目(增补)条件时间和申请程序
  • 原生后台GPS位置限制,降低功耗
  • HarmonyOS NEXT图形渲染体系:重新定义移动端视觉体验
  • 中学数学几百年重大错误:将无穷多各异假R误为R——两数集相等的必要条件
  • ABC391题解
  • 笔试专题(三)
  • 26考研——图_图的代码实操(6)
  • uv包简单使用案例
  • 在 Mac 上使用 Poetry 配置环境变量
  • 【外设】之STIM210陀螺仪学习记录
  • 大数据学习(86)-Zookeeper去中心化调度
  • Python_电商日报_不同数据来源清洗整理成一张表
  • javaweb自用笔记:Mybatis
  • 案例实践 | 招商局集团以长安链构建“基于DID的航运贸易数据资产目录链”
  • 基于大模型预测的初治菌阳肺结核诊疗方案研究报告
  • ORBITVU 欧保图,开启自动化摄影新时代
  • 【精心整理】2025 DeepSeek 精品学习资料合集-共50份(教程+原理解读+行业应用+技术实践).zip
  • 关于瑞芯微开发工具(RKDevTool)刷机下载Boot失败原因的研究
  • 2025-3-25算法打卡
  • H3C交接机初始基本配置
  • 一个网站里面只放一个图片怎么做的/河北seo推广
  • 做网站需要几万吗/百度文库个人登录入口
  • 网站运营与维护是什么/新闻摘抄大全
  • wordpress q a/seo排名赚钱
  • 网站地址结构/微信推广多少钱一次
  • 深圳建设银行网站/2345网址导航主页