Luogu6199 [EER1]河童重工
给出两棵 \(n\) 个点的树,然后求对于一张 \(n\) 个点,\(i, j\) 之间的边权为 \(d_1(i, j) + d_2(i,j)\) 的完全图上最小生成树大小。\(d_i\) 表示在第 \(i\) 棵树上面的距离。
\(1 \le n \le 10^5, w_i \le 5000\)。
图论
最小生成树
Boruvka 算法
点分治
Sub Problem
给定一棵 \(n\) 个节点的树,现有有一张完全图,两点 \(x,y\) 之间的边长为 \(w_x+w_y+dis_{x,y}\),其中 \(dis\) 表示树上两点的距离。求完全图的最小生成树。
\(n \leq 2 \times 10^5\)。
考虑使用 Boruvka 算法
,每次相当于每个点有一个颜色(所属联通块),然后可以考虑换根 DP,每个点维护 {距离它距离的点 \(x\),在所有和 \(x\) 颜色不同的点中距离它最近的点 \(y\)},然后可以求出每个距离每个联通块最近的联通块的距离。单次复杂度 \(\mathcal O(n)\),总复杂度 \(\mathcal O(n \log_2 n)\)。
本题做法
最小生成树可以直接做,或者保留有用边然后直接 Kruskal,这里使用后者。
考虑对于第一棵树进行点分治,然后我们令 \(w_i\) 表示 \(i\) 和当前分治重心的距离,然后将当前分治所涉及的点在第 \(2\) 棵树上面建立虚树。
然后问题相当于考虑一张完全图,每条边的边权为 \(dis(i, j) + w_i + w_j\),求这个图的最小生成树。这个就是子问题了,我们可以求出这个最小生成树的边,然后保留这些重要的边,单次求解最小生成树是 \(\mathcal O(n \log_2 n)\) 的,然后每次保留的边的量级是 \(\mathcal O(n)\) 的,因此总的保留边数是 \(\mathcal O(n \log_2 n)\) 的。
最后再跑一遍 Kruskal,复杂度 \(\mathcal O(n \log ^2_2n)\)。