次小生成树

来源:互联网 发布:真人娱乐系统源码 编辑:程序博客网 时间:2024/05/03 03:25

次小生成树的定义
设 G=(V,E,w)是连通的无向图,T 是图G 的一个最小生成树。如果有另一棵树T1,满
足不存在树T’,ω(T’)<ω(T1) ,则称T1是图G的次小生成树。


求解次小生成树的算法
约定:由T 进行一次可行交换得到的新的生成树所组成的集合,称为树T的邻集,记为N(T)。
定理 3:设T是图G的最小生成树,如果T1满足ω(T1)=min{ω(T’)| T’∈N(T)},则T1是G
的次小生成树。
证明:如果 T1 不是G 的次小生成树,那么必定存在另一个生成树T’,T’=T 使得
ω(T)≤ω(T’)<ω(T1),由T1的定义式知T不属于N(T),则
E(T’)/E(T)={a1,a2
1,……,at},E(T)/E(T’)={b1,b2,……,bt},其中t≥2。根据引理1 知,存在一
个排列bi1,bi2,……,bit,使得T+aj-bij仍然是G 的生成树,且均属于N(T),所以ω(aj)≥ω(bij),
所以ω(T’)≥ω(T+aj-bij)≥ω(T1),故矛盾。所以T1是图G 的次小生成树。
通过上述定理,我们就有了解决次小生成树问题的基本思路。
首先先求该图的最小生成树T。时间复杂度O(Vlog2V+E)
然后,求T的邻集中权值和最小的生成树,即图G 的次小生成树。
如果只是简单的枚举,复杂度很高。首先枚举两条边的复杂度是O(VE),再判断该交换是否
可行的复杂度是O(V),则总的时间复杂度是O(V2E)。这样的算法显得很盲目。经过简单的
分析不难发现,每加入一条不在树上的边,总能形成一个环,只有删去环上的一条边,才能
保证交换后仍然是生成树,而删去边的权值越大,新得到的生成树的权值和越小。我们可以
以此将复杂度降为O(VE)。这已经前进了一大步,但仍不够好。
回顾上一个模型——最小度限制生成树,我们也曾面临过类似的问题,并且最终采用动态规
划的方法避免了重复计算,使得复杂度大大降低。对于本题,我们可以采用类似的思想。首
先做一步预处理,求出树上每两个结点之间的路径上的权值最大的边,然后,枚举图中不在
树上的边,有了刚才的预处理,我们就可以用O(1)的时间得到形成的环上的权值最大的边。
如何预处理呢?因为这是一棵树,所以并不需要什么高深的算法,只要简单的BFS 即可。
预处理所要的时间复杂度为O(V2)。
这样,这一步时间复杂度降为O(V2)。
综上所述,次小生成树的时间复杂度为O(V2)。

 

结论1
     次小生成树可由最小生成树换一条边得到.

证明:
    可以证明下面一个强一些的结论:
    T是某一棵最小生成树,T0是任一棵异于T的树,通过变换
T0 --> T1 --> T2 --> ... --> Tn (T)  变成最小生成树.
所谓的变换是,每次把Ti中的某条边换成T中的一条边, 而
且树T(i+1)的权小于等于Ti的权.
    具体操作是:
    step 1. 在Ti中任取一条不在T中的边uv.
    step 2. 把边uv去掉,就剩下两个连通分量A和B,
            在T中,必有唯一的边u'v' 连结A和B.
    step 3. 显然u'v'的权比uv小 (否则,uv就应该在T中).
            把u'v'替换uv即得树T(i+1).
    特别地:取T0为任一棵次小生成树,T(n-1) 也就是次小生成树且
    跟T差一条边. 结论1得证.

算法:
    只要充分利用结论1, 即得V^2的算法. 具体如下:

step 1.  先用prim求出最小生成树T.
         在prim的同时,用一个矩阵max[u][v] 记录 在T中连结任意两点u,v的唯一的
         路中权值最大的那条边的权值. (注意这里).
         这是很容易做到的,因为prim是每次增加一个结点s, 而设已经标号了的结点
         集合为W, 则W中所有的结点到s的路中的最大权值的边就是当前加入的这条边.
         step 1 用时 O(V^2).
step 2.  枚举所有不在T中的边uv, 加入边uv则必然替换权为max[u][v]的边.

故总时间为O(V^2).

 

针对pku1679 的一些网上结论

这题可以先做一次MST, 然后n-1次循环, 每次删树上的一条边, 再做最小生成树, 取这n-1次中最小的一个就是次小的了, 在稠密图时复杂度接近O(n^3).

 

也可以先做一次MST, 在MST上DFS做下预处理, 算出len[i][j], 表示i到j的路径上最长的边, 预处理复杂度O(n^2).  枚举添加每条不在MST上的边(u,v),加上以后一定会形成一个环, 找到环上权值第二大的边(即除了(u,v)以外的权值最大的边), 把它删掉, 计算当前生成树的权值之和. 取所有枚举修改的生成树权值之和的最小值, 就是次小生成树. 枚举的复杂度是O(m), 总复杂度O(n^2)

 

经过多次测试(我是用Prim做的), 发现PKU的数据是有问题的. 首先, 数据中存在不连通的图, 并且在原图不连通时既不是输出0(测试过输出0就WA), 也不是输出"Not Unique!".

 

不管数据怎么样, 算法写得严谨点就能过, 什么是严谨呢? 比如说在做Prim时, 主循环里选不在现有MST中的最近的点时要判断此点是否是INF(用普通堆的话就不需要这种判断了, 但是映射二分堆还是需要判断一下). 但是这里如果发现最近的点是INF, 并且还不足n-1条边, 不能直接返回0, 而是要把现有的边的总长度返回才能AC...


以上内容都不是原创是学习资料,大家分享下

这里附上我wa的代码,大家帮忙看看