zoukankan      html  css  js  c++  java
  • 算法设计分析(Kruskal构造最小生成树)

    问题:

    给定无向图G(N,M)表明图G有N个顶点,M条边,通过Kruskal算法构造一个最小生成树

    分析:

    算法流程:

    构造好的最小生成树就是step5

    #include<cstdio>
    #include<string.h>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<set>
    #include<map>
    #include<cctype>
    #include<stack>
    #define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define mem(a,x) memset(a,x,sizeof(a))
    #define lson rt<<1,l,mid
    #define rson rt<<1|1,mid + 1,r
    #define P pair<int,int>
    #define ull unsigned long long
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6 + 10;
    const ll mod = 998244353;
    const int inf = 0x3f3f3f3f;
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-7;
    
    int n, m;
    struct node
    {
        int u, v, val;
    }edge[maxn],ansedge[maxn];                                //edge存边的端点u,v,以及边的权值val,ansedge维护构成最小生成树的边的信息
    int  father[maxn];
    int cmp(const node& a, const node& b)                            //对于边的权值大小进行排序    
    {
        return a.val < b.val;
    }
    int find(int x)                                        //通过并查集算法来判断两个顶点是不是同属于同一棵树,可以查找这两个顶点的祖先是否相同,如果相同则说明两个顶点在同一棵树中
    {
        return x == father[x] ? x : father[x] = find(father[x]);
    }
    void MergeTree(int x, int y)                                // 对于不同的两个,通过MergeTree来讲两个树合并成一棵树
    {
        int fx = find(x) , fy = find(y);
        father[fx] = fy;
    }
    
    int main()
    {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= m; ++i)
        {
            scanf("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].val);
        }
        sort(edge + 1, edge + 1 + m, cmp);                        //对边的长度进行排序,在构造最小生成树中的过程中,权值较小的边其优先级总是高于权值大的边
        for (int i = 1; i <= n; ++i)
        {
            father[i] = i;
        }
        int cnt = 0;                                    //cnt记录用于构成最小生成树的边数,根据最小生成树的概念可知,满足条件的边数应该为顶点数-1
        int ans = 0;                                    //ans记录最小生成树的权值和
        for (int i = 1; i <= m; ++i)
        {
            if (cnt == n - 1) break;                        //如果构成最小生成树的边数已经为顶点数-1,那么最小生成树已经构建完成
            if (find(edge[i].u) != find(edge[i].v))                    //判断一条边的两个顶点是否在同一棵树中,如果在同一棵树中则该边为无效边,不能用于构造最小生成树
            {
                cnt++;                                //记录用于构成最小生成树的边数
                MergeTree(edge[i].u, edge[i].v);                //因为该边将两个不同的树进行了连接所以需要合并成一颗树
                ans += edge[i].val;                        //维护最小生成树的权值和
                ansedge[cnt] = edge[i];                        //维护构成最小生成树的边的信息
            }
        }
        printf("最小生成树的权值和为:%d
    ", ans);
        printf("构成最小生成树的边为
    ");
        for (int i = 1; i <= cnt; ++i)
        {
            printf("%d %d %d
    ", ansedge[i].u, ansedge[i].v, ansedge[i].val);
        }
        return 0;
    }
    Kruskal
  • 相关阅读:
    c++ ::和:
    c++ extern
    c++ cpp和hpp
    c++ include
    caffe调试
    caffe blob理解
    poj3126
    FFmpeg滤镜使用指南
    Android之Activity之间传递对象
    Server Tomcat v8.0 Server at localhost failed to start.
  • 原文地址:https://www.cnblogs.com/DreamACMer/p/12386792.html
Copyright © 2011-2022 走看看