zoukankan      html  css  js  c++  java
  • 最小生成树算法MST_kruskal算法

    每日一贴,今天的内容症结字为最小生成树算法

        MST(minimum spanning tree)即最小生成树算法,经典的有两个,这里分析一下kruskal算法。关于另外的一个prim算法,本blog也将分析。
    何谓最小生成树呢?大家知道树就是每一个结点可以互相到达,并且没有环的一种数据结构,这里就不多分析了,何谓最小生成树呢?就是从一个图中选取若干条边,这些边使得每一个结点之间可以互相到达,最症结就是,选取的这些边的权值之和是最小的。
    下面看一个图
    最小生成树和算法
    那么这个图的最小生成树就是
    最小生成树和算法
    下面我们分析一下kruskal算法的基本思想,然后再对照算法看看下面那棵最小生成树是如何生成的
    1.从图中选取权值最小的一条边将权值加到sum中(sum记录最小生成树的边的总权值)
    2.继承图里头选取权值次小的边加到sum,但是当前继承选边有个条件,即所选的边与前面选的边不能形成环(因为这是求最小生成树嘛)
    3.重复2步骤直到选了|V|-1条边(V代表图的结点总数),为什么呢?因为一棵树的的边数比结点数少1嘛
    这里的症结是如何判断它是不是有环(建议读者去看看本blog的对于并查集的讲解,或者去看别人的(呵呵))
    这里简单举个例子分析一下比如说图a中,我们先选了3-6这条边,于是设置parent[6]=3,然后又选4-6这条边
    因为6的父亲是3,比4小,于是我们设置parent[4]=3,假设我们要选3-4这条边,由于初始化父亲的时候设置的parent[3]=3本身,这个时候我们发明parent[3]=3,parent[4]也等于3,于是判定这形成了环(很奇妙吧。),当然这只是简单分析,建议没学过并查集的读者,先去看看并查集再看本blog。
    好了,算法的基本思想就是这样,其实就是贪心嘛,当初我们看看上图的最小生成树是如何生成的
    最小生成树和算法最小生成树和算法
    1.先对边进行排序(sort函数很快嘛。)
    2.选1-3这条边,再选4-6这条边,再选2-5这条边,再选3-6这条边,再选1-4或者2-3,选1-4的时候,我们发明形成了环(1-3-6-4-1),于是不选他,选2-3。终究选了6-1=5条边。

        最后贴下模板

        

        每日一道理
    生命,是一场漫长的棋局。这盘棋没有猎猎西风,没有四起狼烟,只有在取舍和进退中抉择。只有像棋中的小卒那样,勇往直前,毫不退缩沿着沟沟坎坎的人生之路,艰难而执着的求索,前进,才会谱写人生最壮丽的强者之歌。
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    int parent[101];
    struct Edge
    {
         int u,v;
         int len;
    };
    struct Graph
    {
        int vexnum;
        int vecnum;
        Edge edge[10001];
    }G;
    bool cmp(Edge a,Edge b)
    {
         return a.len<b.len;
    }
    void Unitparent(Graph G)
    {
        int i;
        for(i=1;i<=G.vexnum;i++)
        parent[i] = i;
    }
    int Find(int x)
    {
        int i=x,tem;
        while(i!=parent[i])//找到祖先
        i = parent[i];
        while(i!=x)//非递归压缩路径
        {
            tem = parent[x];
            parent[x] = i;
            x = tem;
        }
        return i;
    }
    void Unionset(int x,int y)
    {
        int x1 = Find(x),y1 = Find(y);
        if(x1>y1) parent[x] = y1;
        else parent[y] = x1;
    }
    int kruskal(Graph G)
    {
        int i;
        int sum_weight = 0;
        int num = 0;//已选边的数目
        sort(G.edge,G.edge+G.vecnum,cmp);
        Unitparent(G);//初始化全部顶点的祖先
        for(i=0;i<G.vecnum;i++)
        {
               if(Find(G.edge[i].u)!=Find(G.edge[i].v))//没有形成环
                 {
                     sum_weight += G.edge[i].len;
                     num++;//所选边数+1
                     Unionset(G.edge[i].u,G.edge[i].v);//并查集的合并操作
                     if(num>=G.vexnum-1) break;
                 }
        }
        if(num<G.vexnum-1) return 0;//算选的边数比结点数-1小,此图确定不是连通图咯,最小生成树不存在。
        return sum_weight;
    }

        推荐题目

        http://acm.hdu.edu.cn/showproblem.php?pid=1863

    文章结束给大家分享下程序员的一些笑话语录: 自从有了Photoshop,我再也不相信照片了!(没有Photoshop的年代,胶片照片年代做假的也不少,那时候都相信假的!)

  • 相关阅读:
    景瑞地产商业智能BI整体实施过程
    域名访问和IP访问问题
    sitemesh定义多个装饰器
    8.8.2 EXPLAIN Output Format 优化输出格式
    Python_List对象内置方法详解
    Python_List对象内置方法详解
    Python_序列对象内置方法详解_String
    Python_序列对象内置方法详解_String
    CentOS设置服务开机启动的两种方法
    perl 没有关键文件句柄引起的逻辑错误
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3074196.html
Copyright © 2011-2022 走看看