zoukankan      html  css  js  c++  java
  • 最小生成树:Prim算法和Kruskal算法

    最小生成树:Prim算法和Kruskal算法

    一、什么是最小生成树?

    最小生成树是一副连通加权无向图中一棵权值最小的生成树。
    如:

    二、Prim算法和Kruskal算法的原理

    Prim算法原理:

    1)以某一个点开始,寻找当前该点可以访问的所有的边;
    2)在已经寻找的边中发现最小边,这个边必须有一个点还没有访问过,将还没有访问的点加入我们的集合,并记录添加的边;
    3)寻找当前集合可以访问的所有边,重复(2)的过程,直到没有新的点可以加入;
    4)此时由所有边构成的树即为最小生成树。

    Kruskal算法原理:

    1)将边按权从小到大进行排序;
    2)依次进行加边操作:如果新加的边连接两个互不联通的点,那么就把边连接上并更新连通性(这里建议运用并查集数据结构来维护),否则忽略该边
    3)重复(2)的过程,直到所有点都连通(或者加了n-1条边);
    4)此时由所有边构成的树即为最小生成树。

    总之,Prim算法以点为对象不断更新集合来构成最小生成树;Kruskal算法则是以边为对象不断更新集合来得到最小生成树。破边法和Kruskal算法内核一致,只是操作刚好相反,此不赘述。(对于一个稠密图,prim算法要优于Kruskal算法,但是Kruskal更好写啊QAQ)

    实战1:Prim

    暂时空缺

    实战2:Kruskal

    P2212浇地


    思路:先生成完全图,然后生成最小生成树,鉴于该题要求选的边不小于C,因此选用Kruskal算法直接忽略不符合的边即可

    赋AC代码(用到并查集模板):

    #include <stdio.h>
    #include <stdlib.h>
    #define MAXN 2000
    int fa[MAXN+1];
    typedef struct maye
    {
        int x, y;
    }ccc;
    typedef struct mayeye
    {
        int u, v, l;
    }ddd;
    void init(int n)
    {
        for(int i = 1; i <= n; i++)
        {
            fa[i] = i; //初始化
        }
    }
    
    int find(int x)
    {
        if(fa[x]==x)
            return x;
        return fa[x] = find(fa[x]); //查询时进行路径压缩
    }
    
    void merge(int x, int y)
    {
        fa[find(x)] = find(y); //合并
    }
    
    int com(const void *a, const void *b)
    {
        return (*(ddd *)a).l - (*(ddd *)b).l;
    }
    
    int main(void)
    {
        int n, c;
        scanf("%d %d",&n,&c);
        ccc dot[n+1];
        for(int i = 1; i <= n; i++)
        {
            scanf("%d %d",&dot[i].x, &dot[i].y);
        }
        int m = n*(n-1)/2, t = 1;
        ddd arc[m+1];
        for(int i = 1; i <= n; i++) //按题要求生成所有边
        {
            for(int j = i+1; j <= n; j++)
            {
                arc[t].u = i;
                arc[t].v = j;
                arc[t].l = (dot[i].x - dot[j].x)*(dot[i].x - dot[j].x)+(dot[i].y - dot[j].y)*(dot[i].y - dot[j].y);
                t++;
            }
        }
        //Kruskal
        qsort(arc+1, m, sizeof(ddd), com); //将边按权排序
        init(n);
        int ans = 0, answer = 0;
        for(int i = 1; i <= m; i++)
        {
            if(arc[i].l<c)
                continue;
            if(find(arc[i].u)!=find(arc[i].v)) //符合情况选边
            {
                answer+=arc[i].l;
                ans++;
                merge(arc[i].u, arc[i].v);
            }
            if(ans==n-1)  //得到最小生成树就输出答案
            {
                printf("%d
    ",answer);
                return 0;
            }
        }
        printf("-1
    ");
        return 0;
    }
    
    
  • 相关阅读:
    最好的云备份选项
    不要让你的云备份策略退居次位
    了解区域类型
    Managing WMI security
    创建、导入、导出、复制以及粘贴 WMI 筛选器
    Gpfixup
    centos 7 安装MySQL 5.7.23
    centos 7 配置 mysql 5.7 主从复制
    oracle DG搭建
    undo表空间丢失、损坏
  • 原文地址:https://www.cnblogs.com/SpicyArticle/p/12149339.html
Copyright © 2011-2022 走看看