题目描述:
给定一张 N 个点 M 条边的无向图,求无向图的严格次小生成树。
设最小生成树的边权之和为 sum,严格次小生成树就是指边权之和大于 sum 的生成树中最小的一个。
输入格式
第一行包含两个整数 N 和 M。
接下来 M 行,每行包含三个整数 x,y,z,表示点 x 和点 y 之前存在一条边,边的权值为 z。
输出格式
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
数据范围
N≤10^5,M≤3×10^5
输入样例:
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
输出样例:
11
分析:
本题要求严格的次小生成树,之前在AcWing 1148 秘密的牛奶运输里也曾求过次小生成树,但是本题的数据范围更大,对时间复杂度的要求也更高。回忆下秘密的牛奶运输那题的基本思路。
在最小生成树中,连接生成树中任意两点u和v,则上图中由u到v构成的回路中,uv的长度一定是该回路中边权长度的最大值,否则原来的生成树一定就不是总边权最小的生成树。
u到v的回路由生成树上u到v的若干树边以及uv这条非树边构成。设最小生成树的边权之和为sum,u到v的树边中最大的边权是m1,第二大的边权是m2,uv的长度为w。则可能存在两种情况:
第一种情况,u到v的树边中所有的边权都小于w。此时sum + w - m1是次小生成树边权之和的候选解,也就相当于擦掉u到v的树边中边权最大的那条树边,再连接上uv生成的一个新的生成树。
第二种情况,u到v的树边中最大的边权m1等于w,此时擦掉边权为m1的树边,连上uv得到的还是最小生成树,为了得到严格的次小生成树,只能擦掉边权第二大的树边m2,连上uv,得到的次小生成树边权之和的候选解是sum + w - m2。
遍历下所有的候选解,就可以得到次小生成树的边权和了。
观察下秘密的牛奶运输的代码可以发现,该题代码的实现流程一共包括:用结构体存储边的信息,然后用kruskal算法求解最小生成树,并用邻接表存储生成树的信息,接着用dfs求最小生成树中最大和次大边权,最后遍历下非树边求解。这里每次执行dfs求最小生成树上两点路径中的最大和次大边权的时间复杂度都是O(n),总的时间复杂度就是O(n^2),本题需要用更高的效率求解次小生成树,因此需要优化生成树中两点间路径的最大和次大边权的求法。
可以使用求LCA的树上倍增法进行求解,树上倍增法的详细介绍见AcWing 1172 祖孙询问。也就是说本题总的解题流程与秘密的牛奶运输那题基本一致,只是在求最大、次大边权的方法上有所不同。
设d[i][k]表示树上的某