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
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步