• 最小生成树及最大生成树(算法及正确性简单证明)


    最小生成树

    kruskal

    kruskal算法步骤:

    1. 将所有边按权值从小到大排序
    2. 将边按序加入最小生成树
      a. 如果该边连接的两点已经属于一个集合,则舍弃该边
      b. 如果该边连接的两点不属于一个集合,则加入该边,并将所连两点用并查集合并
    3. 当加入n-1条边后得到的就是该图的最小生成树

    这么做时间复杂度为(O(Mlog M)),M为边的总数,这是给所有边按权排序的时间复杂度,之后并查集的时间复杂度我不太清楚,大概在(O(Nlog N))
    这里用到了贪心思想,也许你会怀疑:为什么这么做是对的?
    证明应该分为两部分:首先证能连成树,再证这种连法是权值最小的。
    首先第一部分十分显然,一个n个点的连通图一定能连成一棵树。
    主要来看第二部分:
    如果当前边连接的两点不在一个集合里,按照kruskal算法应该加入该边,我们假设舍弃会有更好的结果,最后得到一棵不含该边的最小生成树,我们此时再把该边加入,一定会出现一个环,在该环上不可能所有边比这条边小,如果所有边比这条边小,那么会与我们在加入该边时这两个点时不连通情况矛盾,那么这个环上一定有边的权值是大于等于该边的,如果我们用这条边把权值大于等于该边的边替换,得到的生成树权值不会大于原生成树,所以能加入时加入这一策略是对的。由此证明了贪心的正确性。

    prim

    prim算法步骤我懒得写了,提一嘴时间复杂度是(O(Nlog N)),接着我简单证明一下正确性吧
    prim算法也是运用贪心的思想。要证明prim算法是对的,关键是要证,对于一个集合,离集合最近的边一定是在最小生成树上。
    算了,懒得证了,哪天有时间再补吧

    最大生成树

    顾名思义,最大生成树就是权值最大的生成树。
    我们很容易想到:按照最小生成树的做法反过来做不就好了?
    但这样对吗?
    按照以上最小生成树贪心正确性的证明,我认为这样是对的。
    当然,有一种更保险的做法,把所有边边权改为(X-W)(X)是我们赋的一个很大的数,再跑一遍最小生成树,得到的结果是(X*(N-1)-sum W),因为(X*(N-1))是一个常数,所以减去该常数取反得到的一定是最小生成树权值和。

  • 相关阅读:
    判断是否声明了某个特性
    如何月份英文缩写字符串转日期
    要捕捉System.Exception异常吗
    jenkins发布到nuget
    C# – Record, Class, Struct
    Google Maps Embed API & JavaScript API
    图片综合知识
    ASP.NET Core – ADO.NET
    CSS – 管理
    JavaScript Library – PhotoSwipe
  • 原文地址:https://www.cnblogs.com/Knowledge-Pig/p/13761703.html
Copyright © 2020-2023  润新知