对求次小生成树的感悟
我相信对于求最小生成树,各位肯定并不陌生。以Kruskal算法为例,就是对各边按边权由小到大排序,然后一条条插入,用并查集判断是否成环,直至操作到成为n个点的树为止,在这里并不仔细赘述。
然而求次小生成树应该怎么做呢?按照Kruskal算法的思想,是不是按最小生成树的方法建成树后插入剩余边中的最小权边,然后再删去唯一环中权值最大的边就可以了呢?
然而机智的你肯定发现了吧,这并不是正确的做法。因为我们并不知道删去的边的值是多少,有可能你插入的边的权值较大,但可以删去权值更大的边从而使总权值成为次小。
那我们该怎么做呢?按照上面的说法,我们直接暴力枚举剩余边,然后分别寻找环中权值最大的边删去,之后在之中取最小权值不就好了吗(暴力出奇迹)?(m为图的总边数,n为点数)此时按此方法的时间复杂度为O(mn)。感觉海星,可是相对于最小生成树的O(mlogm)来说,复杂度似乎有亿点高。
那我们又有什么优化的方法呢?我们发现每次枚举剩余边后,都要用O(n)的时间来找到树中两点路径中的最大权值边,是不是有点太麻烦了呢?一想到树上两点路径间的问题,我们就会飞快地想到lca,那我们只需用倍增或者树链剖分的方法来找到两点间路径的最大边权,复杂度为O(logn),那么总的复杂度就被优化为O(mlogn)啦!(针不辍.jpg)
综上,次小生成树的做法为最小生成树+枚举剩余边+lca,总复杂度仍为O(mlogm)
例题与代码:(以后再补)