最小生成树 普利姆算法

#include <bits/stdc++.h>
using namespace std;

// 定义line结构,一条边的2个端点(x,y) 和权重 quan
struct line{
    int x;
    int y;
    int quan;
};

// 自定义比较器,按quan 升序排列
bool cmp(line& a, line& b){
    return a.quan < b.quan;
}
vector<line> ls(100); // 存储边
vector<int> g(100); // 并查集
// 并查集 找父节点
int ufind(int x){
    if(g[x] == x){
        return g[x];
    }
    g[x] = ufind(g[x]);
    return g[x];
}
int main() {
    int n,m; // n:点数量[1,n], m:边数量 [x ,y ,q]
    cin >> n >> m;
    
    for(int i = 1;i <= m; i++){// 读入边的两个端点和权重
        cin >> ls[i].x >> ls[i].y >> ls[i].quan;
    }
    sort(ls.begin() +1, ls.begin() +1+m, cmp);// 按权重升序
    for(int i = 1; i <= n; i++){// 初始化并查集
        g[i] = i;
    }
    int k = 0;//加入的边的个数
    int dis = 0;// 总消耗
    for(int i = 1;i <=m; i++){
        // ls排完序了,根据权重从小到大
        // 先取出的权重最小
        // 先出来的两个点加入到同一个集合中
        //      1.如果两个点已经在同一个集合中了,不合并了
        //      2.合并前期可能有 1 - 2    ;  3 - 4 -5  两个集合这种情况
        //         那么先让这个两个集合分别合并
        //         之后一定有一次,两个集合中的点会有两个点,让他们产生交集
        int gx = ufind(ls[i].x);
        int gy = ufind(ls[i].y);
        // 两个点已经在集合中了 说明已经在树上了,合并
        // 只要两个点不是同一个集合,那么就将它们合并
        if(gx != gy){
            g[gy] = gx;
            k++;
            dis += ls[i].quan;
        }
        
        if(k > n-1){break;} // 最少的边已经到了,所以break;
    }
    cout << dis;
    return 0;
}

测试用例:
5 7
1 2 3
1 3 2
2 3 1
2 4 1
3 4 4
4 5 2
3 5 5

预期输出:6

posted @ 2022-04-17 23:34  子于舟  阅读(48)  评论(0)    收藏  举报