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:12 山东
码住了,还有吗?
点赞 回复 分享
发布于 2023-05-03 09:27 四川

相关推荐

totoroyyw:千年老妖😂
投递华为等公司10个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务