boruvka算法
一个mst算法。
其用于求解一些特殊的mst问题。
例题1:CF888F
我们要求一个集合到外面的最小边。
对于每个集合维护一个trie表示这个集合内的所有数。
维护一个整体trie,表示所有数。
对于每个集合,枚举这个集合的所有点。然后询问整体trie减去这个集合trie的最小异或和即可。
时间复杂度\(O(n\log_2^2n)\)
当然还有一个做法:考虑按位分治。把高位为\(1,0\)的都递归下去,然后询问两个集合的最小异或和。
例题2:at3611
考虑直接套用boruvka算法。
考虑树上dp。
每个点要记录最大值,与最大值颜色不同的次大值。
然后这样子就能求出和一个点距离最近的点。
然后就能用boruvka了。
另一个做法:把所有边集做若干次mst,排除一定不会选择的边。
然后全局做一个mst,答案不变。
考虑点分,考虑跨越重心的路径。
设\(d_x\)表示\(x\)点到重心的距离。
则我们两个点\(x,y\)的点权可以被表示成\(d_x+a_x+d_y+a_y\)
令\(p_x=d_x+a_x\),则连接两个点\(x,y\)的代价可以被表示成\(p_x+p_y\)
容易发现只要我们求出\(p_x\)的最小值位置\(y\),把所有点和\(y\)连边。
这样子就把跨过分治中心的路径的mst求出来了。
然后最后做一次mst即可。
例题3:病毒实验
其实这道题不是boruvka。但是运用了这个算法的思想。
考虑我们怎么判定一个点是否能被拓展。预处理出\(f_s\)表示有\(s\)集合内的方向,最长连续段的长度。
可以在常数时间*\(O(n)\)内预处理。
考虑把矩阵划分成若干个连通块,每个连通块内有一关键点\(c\)。从连通块任意点都能拓展到\(c\)。
一个显然的性质:如果一个连通块关键点\(b\)能够走到\(c\),那么\(b\)所在连通块不能用于更新答案。
考虑使用这个性质进行bfs。可惜对时间复杂度没有改进。
考虑boruvka算法的时间复杂度证明。
每次给一个连通块通过bfs找到其不在连通块的出边。
然后把它和这个出边所指向的连通块合并。
如果bfs到一个已经被合并的区域就跳出,不用bfs了
可以发现时间复杂度是\(O(RC\log_2 RC)\)
会发现一个点到的合并只有两种:
1.和一个区域合并。
2.bfs到一个被合并过的区域。
会发现1情况使两个连通块变成一个,2情况使一个连通块变成\(0\)个。
所以时间复杂度有保证。
例题4:lg6199
考虑在\(T2\)上进行树分治。
设\(d_x\)表示\(x\)到重心的距离。
连接两个点的代价就是\(d_x+d_y+T1dis(x,y)\)
建立连通块在\(T1\)上的虚树,就转化成例题2了
例题5:https://www.cnblogs.com/ctmlpfs/p/14333369.html