• Kruskal算法求最小生成树 笔记与思路整理


    整理一下前一段时间的最小生成树的算法。(其实是刚弄明白

    Kruskal其实算是一种贪心算法。先将边按权值排序,每次选一条没选过的权值最小边加入树,若加入后成环就跳过。

    先贴张图做个示例。

    (可视化均来自VisuAlgo)

    1、邻接链表按权值排序后(可以直接写个cmp,sort()结构体):

    2、依次选边,若成环则跳过,否则加入最小生成树并计数。

      这里判断是否成环用的是并查集:如果新加入的边两个端点在同一个集合中,就说明已经有一条路径联通这两个端点。

    3、重复2,直到加入了n-1条边或遍历完成(无最小生成树)。

    选取1号、4号、7号后:

    选取6号(1--4),成环,跳过;

    加入5号(2--3),达到n-1条,最小生成树形成。

    代码实现:

    #include <bits/stdc++.h>
    #define maxn 100010
    using namespace std;
    
    struct edge{
        int from, to, val;
    };
    edge tree[maxn];
    bool cmp(const edge &a, const edge &b){
        return a.val < b.val;
    }
    int m, n, father[maxn], rslt = 0;
    bool possible = true;
    
    int get_father(int x){
        if(father[x] == x) return x;
        return father[x] = get_father(father[x]);
    }
    void kruskal(){
        int f1, f2, cnt = 0;
        for(int i=1; i<=n; i++){
            father[i] = i;
        }
        for(int i=1; i<=m; i++){
            f1 = get_father(tree[i].from);
            f2 = get_father(tree[i].to);
            if(f1 != f2){
                rslt += tree[i].val;
                father[f1] = f2;
                if(++cnt == n-1){
                    return;
                }
            }
        }
        possible = false;
        cout << "Impossible!";
        return;
    }
    
    int main(){
        cin >> n >> m;
        for(int i=1; i<=m; i++){
            cin >> tree[i].from >> tree[i].to >> tree[i].val;
        }
        sort(tree+1, tree+m+1, cmp);
        kruskal();
        if(possible) cout << rslt;
        return 0;
    }
  • 相关阅读:
    提交代码报错不同方式
    pow log 与 (int)
    优先队列的创建
    积性函数
    静态主席树,动态主席树(一种可持久化线段树)
    codeblocks 输入、输出文件的位置
    后缀自动机
    BellmanFord 最短路
    struct
    hdu1501 动态规划
  • 原文地址:https://www.cnblogs.com/miserweyte/p/11400549.html
Copyright © 2020-2023  润新知