P3206 城市建设 题解

Statement

动态边权的最小生成树。\(n\le2\cdot10^4,m,q\le5\cdot10^4\)

Solution

法一:改边权相当于删一条边再加一条边. 考虑 LCT 维护最小生成树,加边好做,但删边比较麻烦,于是采用线段树分治,撤销一条边是好做的,cut 再 link 一下就行了. \(O(n\log n\log q)\),常数较大.

法二:两个结论:已知原图的一个边集 \(S\)

  • \(S\) 所有边权设为 \(-\inf\),记此时原图的最小生成树的不属于 \(S\) 的边的集合为 \(T\),接下来 \(S\) 每条边无论边权取何值,原图的最小生成树还包含 \(T\).

    简洁证明:\(S\) 边权的改变只会使 \(S\) 中被选上的边变少,而一条边被选入 \(T\) 当且仅当它连接了两个之前从未连通的连通块,容易发现 \(T\) 中的这些边的连接作用是即使 \(S\) 中的边也无法替代的,所以必须被选上.

  • \(S\) 所有边权设为 \(\inf\),在原图中找出最小生成树,记不在树边上的非 \(S\) 边的集合为 \(T\),接下来 \(S\) 每条边无论边权取何值,原图的最小生成树不包含 \(T\).

    简洁证明:\(S\) 边权变小只会让 \(S\) 加入的边变多,假如 \(S\) 中一条边加入,考虑 LCT 维护最小生成树的过程,被替换的一定是树边,也就是非树边一定不会反而成为树边.

考虑如何把两个结论用起来:

还是把修改看成一次加入和删除,发现按结论,加边可能可做,但删边是显然困难的;再考虑线性扫一遍处理询问的过程,发现一个询问前面的所有修改都已经应用,而它后面的所有修改还未应用;再往右扫一个,发现难点在于我们无法知道当前最小生成树形态。这启发我们按时间分治.

设当前处理的操作区间为 \([l,r]\),此时该区间内的边我们不确定,但其他边我们都确定了;说具体点就是 \([1..l-1]\) 内的边权已被修改,\([r+1,q]\) 内的边权还未修改,但 \([l,r]\) 内的修改将要处理,还不知道这些边的修改情况。这时假如我们往左走,右半部分就被确定;假如往右走,左半部分就被确定。现在的问题变成了求加入一些边后的最小生成树.

考虑上面两个结论:第一个告诉我们已确定的边中有一些是一定被选的,这样可以先把这些边组成的连通块缩点,算出边权和;第二个告诉我们可以删除一些无用的边. 假如我们在进入 \([l,r]\) 时已经得到这样简化后的图,该区间的长度为 \(len\),估计一下边和点的量级:

对于第一个操作,最多 \(2\cdot len\) 个点不能被缩,此时 \([l,r]\) 组成的边集形成 \(len\) 个连通块;故点数是 \(O(len)\);而第二个操作保证了边与点的量级同阶,故可以直接暴力加边 Kruskal,注意还要维护这个简化后的图,即还要缩点、删边.

缩点用可撤销并查集,删边随便记录一下,就做完了,注意递归到底时要把该操作进行了,即更改该边权值、输出答案.

然后做完了,若 Kruskal 为单 log,\(T(n)=2T(\frac n2)+O(n\log n)=O(n\log^2n)\).

posted @ 2024-07-19 21:31  Laijinyi  阅读(7)  评论(0编辑  收藏  举报