[BJWC2010] 严格次小生成树

严格次小生成树

题解

小蓝书 + 我自己的补充

做法

题意很好理解吧。
设最小生成树的边权之和为 \(sum\)
我们要找严格次小生成树,就是要找到这样的一条非最小生成树上的边,满足:

将最小生成树上的某条边替换成这条边后,树依然联通。

这条边与被替换边的权值之差最小,且大于 \(0\)

所以我们进行如下操作:

选择一条非最小生成树上的边 \((x,y,z)\)

将它加入树中,显然会形成一个环。

\(Kruskal\) 的证明过程我们可以得到,\(z \geq dis_{x,y}\)

所以我们可以将 \(x\) - \(y\) 路径上的某条边替换成边 \((x,y,z)\) ,显然树依然联通。

\(x\) - \(y\) 路径上的权值最大边的边权为 \(val_1\) ,次大边的边权为 \(val_2\)

根据上述严格次小生成树的找法的定义, 当 \(z > val_1\) 时 ,将 \(val_1\) 的这条边替换成 \((x,y,z)\) 肯定是最优的,得到候选答案 \(sum - val_1 + z\)。当 \(z = val_1\) 时,将 \(val_2\) 替换成 \((x,y,z)\) 肯定是最优的,因为 \(val_1\) 所在的边不能被替换,得到候选答案 \(sum - val_2 + z\)

对所有的非树边执行上述操作,记录最小的范围值,得到最终答案。

优化

显然每次暴查 \(val_1,val_2\) 明显会炸。
所以我们可以运用倍增的思想预处理出点 \(x\) 向上跳 \(2^k\) 次的路径中的 \(val_1\)\(val_2\)
做法类似与 \(lca\) 倍增做法时维护祖先的做法,这到题我们在找 \(x\) - \(y\) 的路径时也需要 \(lca\) ,所以这两个我们也需要维护出来。
\(g[x][k][0/1]\) 表示点 \(x\),向上跳 \(2^k\) 次的路径中的 \(val_1\)\(val_2\)

初始化:

\[g[x][0][0] = w_{x,fa_x},g[x][0][1] = -INF(设为负无穷不为影响到其它值的维护) \]

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zggsyw.html