其他分享
首页 > 其他分享> > AcWing 356 次小生成树

AcWing 356 次小生成树

作者:互联网

题目传送门

一、题目分析

本题要求严格的次小生成树,之前在\(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]\)表示树上的某节点\(i\)向上走\(2^k\)步到达的节点,则状态转移方程为\(d[i][k] = d[d[i][k-1]][k-1]\),不妨令\(j = d[i][k-1]\),则状态转移方程可以表示为\(d[i][k] = d[j][k-1]\),直观的理解就是要想到达离\(i\)距离为\(2^k\)的节点,只需要先走\(2^(k-1)\)步到达\(j\)节点,再从\(j\)节点走\(2^(k-1)\)步就到达了目的节点。

令\(f[i][k][0]\)表示\(i\)到\(d[i][k]\)节点路径上的最大边权,\(f[i][k][1]\)表示次大边权,显然\(f[i][k][0] = max(f[i][k-1][0],f[j][k-1][0])\),也就是\(i\)到\(d[i][k]\)一共有\(2^k\)条边,边权的最大值是\(i\)到\(j\)中边权的最大值与\(j\)到\(d[i][k]\)中边权的最大值中的较大者。\(f[i][k][1]\)的求解就需要分情况讨论了:

f[i][k-1][0] == f[j][k-1][0]时,f[i][k][1] = max(f[i][k-1][1],f[j][k-1][1];
f[i][k-1][0] > f[j][k-1][0]时,f[i][k][1] = max(f[i][k-1][1],f[j][k-1][0],;
f[i][k-1][0] < f[j][k-1][0]时,f[i][k][1] = max(f[i][k-1][0],f[j][k-1][1];

标签:树边,边权,uv,最小,生成,356,节点,AcWing
来源: https://www.cnblogs.com/littlehb/p/16074758.html