美文网首页
最小生成树——Kruskal

最小生成树——Kruskal

作者: 四川孙一峰 | 来源:发表于2017-01-13 20:16 被阅读0次

    图论算法理论、实现及应用样例

    图3.3(a).jpg

    例 3.1

    利用Kruskal算法求图3.3(a)所示的无向网的最小生成树,并输出一次选择的各条边及最终所得的最小生成树的权。

    输入

    7 9
    1 2 28
    1 6 10
    2 3 16
    2 7 14
    3 4 12
    4 5 22
    4 7 18
    5 6 25
    5 7 24

    输出

    1 6 10
    3 4 12
    2 7 14
    2 3 16
    4 5 22
    5 6 25
    sumweight = 99

    分析

    在下面的代码中首先读入各边的信息,存放在数组edges中,并按照权值从小到大进行排序。Kruskal函数用于实现Kruskal算法: 首先初始化并查集,然后从edges中依此选用边,若边的两个顶点在同一连通分量,则弃用这条边,否则合并。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxp = 11;  // 顶点最大个数;
    const int maxl = 20;  // 边的最大个数;
    
    struct edge
    {
        int u,v,w;     // 边的数据 ; u , v 分别构成这条边的两个点 ; w 为这条边的权值;
    }edges[maxp];  //  边的数组;
    
    int father[maxp];
    
    int p,l;
    
    int Find( int x )             //查找并返回节点x所属集合的根节点,顺带压缩路径。
    {
        if(father[x] < 0) return x;
        return father[x]=Find(father[x]);
    }
    
    
    void Union( int R1 , int R2 )      //把两个不同元素合并,使两个集合中任意两个元素都连通;
    {
        int r1 = Find(R1);
    
        int r2 = Find(R2);
        int tmp = father[r1] + father[r2];   // 两个集合节点个数和为负数;
    
        if( father[r1] > father[r2])    // 优化方案——加权法则;
        {
            father[r1] = r2;  father[r2] = tmp;
        }
        else
        {
            father[r2] = r1;  father[r1] = tmp;
        }
    }
    
    bool cmp(edge a,edge b)
    {
        if(a.w != b.w) return a.w < b.w ;
    }
    
    int Kruskal()
    {
         int sumweight = 0;
         int num = 0 ;       //已用边的个数;
         int u,v;
         memset(father,-1,sizeof(father));     // 初始化father数组;
         for(int i = 0 ; i < l ; i++)
         {
             u = edges[i].u; v = edges[i].v;
             if(Find(u) != Find(v))
             {
                 printf("%d %d %d\n",u,v,edges[i].w);
                 sumweight += edges[i].w;   num++;
                 Union(u,v);
             }
             if( num >= p-1) break; // 取到 p-1 条边的时候退出;
         }
         printf("sumweight = %d\n",sumweight) ;
    }
    
    int main()
    {
        int u , v, w ;
        scanf("%d%d",&p,&l);
        for(int i = 0 ; i < l ; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            edges[i].u = u; edges[i].v = v; edges[i].w = w;
        }
        sort(edges,edges+l,cmp);
        Kruskal();
    }
    
    

    相关文章

      网友评论

          本文标题:最小生成树——Kruskal

          本文链接:https://www.haomeiwen.com/subject/tpbsbttx.html