Kruskal和并查集-最小生成树

并查集

vector<int> parent;(节点的根)
vector<int> rank;(按秩排序)
//初始化parent和rank数组
void Dset(int _n){
        parent.resize(_n);
        rank.resize(_n, 1);
        for(int i = 0; i < _n; i++){
            parent[i] = i;
        }
};
//寻找当前节点的根
int find(int a){
        return parent[a] == a ? a : find(parent[a]);
    }
// 合并两个节点
bool merge(int x, int y){
        int fx = find(x), fy = find(y);
        if(fx==fy){
            return false;
        }
        if(rank[fx] < rank[fy]){
            swap(fx ,fy);
        }
        rank[fx] += rank[fy];
        parent[fy] = parent[fx];
        return true;
    }

struct Edge{
        int len, start, end;
        Edge(int len, int start, int end) : len(len), start(start), end(end){};
    };

Main函数

int minCostConnectPoints(vector<vector<int>>& points) {
       
        auto dis = [&](int x, int y) -> int{
            return abs(points[x][0] - points[y][0]) + abs(points[x][1] - points[y][1]); 
        };
        vector<Edge> edge;
        int n = points.size();
        Dset(n);
        for(int i = 0; i < n; i++){
           for(int j = i+1; j < n; j++){
               edge.emplace_back(dis(i, j), i, j);
            } 
        }
        sort(edge.begin(), edge.end(), [](Edge a, Edge b) -> bool{ return a.len < b.len;});
        int res = 0;
        int num = 0;
        for(auto & [len, i, j] : edge){
            if(merge(i, j)){
                res += len;
                num++;
                if(num==n-1)
                    break;
            }
        }
        return res;
    }

流程介绍

  1. 计算节点之间的距离:匿名函数lamda,//points[x]表示第一个节点,points[y]表示第二个节点, 不要搞混
  2. 初始化并查集
  3. 初始化边edge
  4. 边按从小到大排序
  5. 遍历边的每一对节点,每次merge两个节点,res加上边的权值,合并一次节点num++,直到num==n-1,表示边的数量已经是最小生成树了

tips

  1. 匿名函数 auto dis = [&](int a) ->{ return a; };

这里的[&],表示Lambda表达式中的一种捕获方式,&表示按引用捕获函数参数,好处是不需要拷贝points数组,减少内存开销;

2. 有参构造:成员初始化列表的语法是在构造函数参数列表之后加上冒号,之后是一系列成员变量和它们对应的初值,使用逗号分隔。

struct Edge{

        int len, start, end;

        Edge(int lenint startint end) : len(len), start(start), end(end){};

    };

3.有趣的点,在merge函数中,parent[fy] = fx;和parent[fy] = parent[fx];是等价的,这是因为在 parent 数组中存储的值实际上并不是每个点的父节点,而是每个点所属的连通分量的代表元素(即根节点)。因此,parent[fy] = parent[fx] 的作用实际上是将 fy 所属的连通分量的根节点更新为 fx 所属的连通分量的根节点,从而将两个连通分量合并成一个。

全部评论
码住了,还有吗?
点赞 回复 分享
发布于 2023-05-03 09:27 四川
求更多例子和练习
点赞 回复 分享
发布于 2023-05-03 09:12 山东

相关推荐

家人们,我现在真的好纠结。我是26届的,目前还没有实习过。我现在的情况是,想参加秋招,但是感觉自己的简历特别空,没有实习经历会不会秋招直接凉凉啊?可我又听说现在很多公司对26届实习生也不太感冒,说什么不确定性大。而且我最近在准备考公,时间上也有点冲突。要是把时间花在实习上,备考时间就少了。但要是不实习,又怕以后就业有问题😫有没有懂行的友友帮我分析分析:26届现在不实习,秋招找工作真的会很难吗?考公和实习该怎么平衡啊?如果现在不实习,考完公再去找实习还来得及吗?真的太焦虑了,希望大家能给我点建议🙏
小破站_程序员YT:我可能和大家的观点不一样。人的精力是有限的,不能既要还要。你又想实习又想考公最后又要秋招上岸,我觉得哪有那么多的选择。你如果想考上岸,那就全力以赴。如果想秋招上岸,就继续投实习,投没了,就继续准备秋招,秋招不行继续春招。别到最后,考公没上岸,觉得是花了时间浪费在找实习上了, 秋招没上岸,觉得是浪费时间准备考公去了。我是认为很难说可以去平衡 不喜勿喷,可以叫我删除
实习与准备秋招该如何平衡
点赞 评论 收藏
分享
05-26 22:25
门头沟学院 Java
Java小肖:不会是想叫你过去把你打一顿吧,哈哈哈
点赞 评论 收藏
分享
06-10 23:36
已编辑
首都经济贸易大学 C++
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务