• LeetCode-1135. Connecting Cities With Minimum Cost [C++][Java]


    LeetCode-1135. Connecting Cities With Minimum CostLevel up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.https://leetcode.com/problems/connecting-cities-with-minimum-cost/There are N cities numbered from 1 to N.

    You are given connections, where each connections[i] = [city1, city2, cost] represents the cost to connect city1 and city2together.  (A connection is bidirectional: connecting city1 and city2 is the same as connecting city2 and city1.)

    Return the minimum cost so that for every pair of cities, there exists a path of connections (possibly of length 1) that connects those two cities together.  The cost is the sum of the connection costs used. If the task is impossible, return -1.

    Example 1:

    Input: N = 3, connections = [[1,2,5],[1,3,6],[2,3,1]]
    Output: 6
    Explanation: 
    Choosing any 2 edges will connect all cities so we choose the minimum 2.
    

    Example 2:

    Input: N = 4, connections = [[1,2,3],[3,4,4]]
    Output: -1
    Explanation: 
    There is no way to connect all cities even if all edges are used.

    Note:

    1. 1 <= N <= 10000
    2. 1 <= connections.length <= 10000
    3. 1 <= connections[i][0], connections[i][1] <= N
    4. 0 <= connections[i][2] <= 10^5
    5. connections[i][0] != connections[i][1]

    【C++】

    1. prim

    • 把一个初始顶点的所有边加入优先队列
    • 取出最短的边,把这条边的另一个顶点相关的边加入队列
    • 再取出最小的边,重复下去,直到所有顶点加入过了
    1. struct cmp {
    2. bool operator()(const pair<int,int>& a, const pair<int,int>& b) const {
    3. return a.second > b.second;//小顶堆, 距离小的优先
    4. }
    5. };
    6. class Solution {
    7. public:
    8. int minimumCost(int N, vectorint>>& connections) {
    9. vector<bool> vis(N+1, false);
    10. vectorint,int>>> edges(N+1,vectorint,int>>());
    11. for (auto& c : connections) {
    12. edges[c[0]].push_back({c[1],c[2]});
    13. edges[c[1]].push_back({c[0],c[2]});
    14. }
    15. priority_queueint,int>, vectorint,int>>, cmp> q;
    16. int to, distance, total = 0, edge = 0;
    17. vis[1] = true;
    18. for (auto& e : edges[1]) {q.push(e);}
    19. while (!q.empty()) {
    20. to = q.top().first;
    21. distance = q.top().second;
    22. q.pop();
    23. if(!vis[to]) {
    24. vis[to] = true;
    25. total += distance;
    26. edge++;
    27. if (edge == N-1) {return total;}
    28. for (auto& e : edges[to]) {q.push(e);}
    29. }
    30. }
    31. return -1;
    32. }
    33. };

    2. Kruskal

    • 将边的权值排序,小的先遍历,用并查集检查两个顶点是否合并了,没有合并则将该边加入生成树
    • 也可以使用优先队列实现(相当于排序)
    1. class dsu {
    2. vector<int> f;
    3. public:
    4. dsu(int n) {
    5. f.resize(n);
    6. for(int i = 0; i < n; ++i) {f[i] = i;}
    7. }
    8. void merge(int a, int b) {
    9. int fa = find(a);
    10. int fb = find(b);
    11. f[fa] = fb;
    12. }
    13. int find(int a) {
    14. int origin = a;
    15. while(a != f[a]) {a = f[a];}
    16. return f[origin] = f[a];
    17. }
    18. };
    19. class Solution {
    20. public:
    21. int minimumCost(int N, vectorint>>& connections) {
    22. dsu u(N+1);
    23. sort(connections.begin(), connections.end(),[&](auto a, auto b) {
    24. return a[2] < b[2];//距离短的边优先
    25. });
    26. int edge = 0, p1, p2, dis, total = 0;
    27. for(int i = 0; i < connections.size(); ++i) {
    28. p1 = connections[i][0];
    29. p2 = connections[i][1];
    30. dis = connections[i][2];
    31. if(u.find(p1) != u.find(p2)) {
    32. u.merge(p1,p2);
    33. edge++;
    34. total += dis;
    35. }
    36. if(edge == N-1) {break;}
    37. }
    38. return edge == N-1 ? total : -1;
    39. }
    40. };

    【Java】

    1. class Solution {
    2. public int minimumCost(int N, int[][] connections) {
    3. Arrays.sort(connections, (a, b) -> a[2] - b[2]);
    4. int res = 0;
    5. UF uf = new UF(N);
    6. for (int [] connect : connections) {
    7. if(uf.find(connect[0]) != uf.find(connect[1])) {
    8. uf.union(connect[0], connect[1]);
    9. res += connect[2];
    10. }
    11. if (uf.count == 1) {
    12. return res;
    13. }
    14. }
    15. return -1;
    16. }
    17. }
    18. class UF{
    19. int [] parent;
    20. int [] size;
    21. int count;
    22. public UF(int n) {
    23. parent = new int[n+1];
    24. size = new int[n+1];
    25. for (int i = 0; i<=n; i++) {
    26. parent[i] = i;
    27. size[i] = 1;
    28. }
    29. this.count = n;
    30. }
    31. public int find(int i) {
    32. if (i != parent[i]) {
    33. parent[i] = find(parent[i]);
    34. }
    35. return parent[i];
    36. }
    37. public void union(int p, int q) {
    38. int i = find(p);
    39. int j = find(q);
    40. if (size[i] > size[j]) {
    41. parent[j] = i;
    42. size[i] += size[j];
    43. } else {
    44. parent[i] = j;
    45. size[j] += size[i];
    46. }
    47. this.count--;
    48. }
    49. }

    参考文献

    【1】大顶堆升序、小顶堆降序的堆排序(以Java描述为例版本)

  • 相关阅读:
    【软考-中级】系统集成项目管理工程师-质量管理历年案例
    网络安全(黑客)自学
    vsftpd 配置-使用虚拟账户登录
    人工智能:人脸识别技术应用场景介绍
    Vue之transition组件
    SpringMvc(二、请求传参
    工业互联网安全下的数据分类分级研究
    Java面向对象三大特性:继承、封装、多态
    贪心算法(活动安排问题)
    2013年第四届C/C++ A组蓝桥杯省赛真题解析
  • 原文地址:https://blog.csdn.net/qq_15711195/article/details/126447763