洛谷 P6199 [EER1]河童重工 题解

题面

题意:

给定两棵 n 个点的带边权树。

求包含 n 个点的,ij 之间边权为 d1(i,j)+d2(i,j) 的完全图的最小生成树大小。

其中 dx(i,j) 表示 ij 两点在第 x 棵树上的距离。

数据范围:n105

子问题:Tree MST

先来考虑子问题的解法:

  • 有一个结论:如果我们把边集分成两部分,对这两部分分别求 MST,然后再合并起来,就是原图的 MST。
  • 由于问题建立在树上,因此考虑树分治。
  • 在点分治的过程中,考虑跨过分治重心的路径。设分治重心为点 xfu=disu,x+wu,那么把两个点 uv连起来的边权就是 fu+fv。很明显,对于当前分治重心控制的所有节点,肯定是都和 f 值最小的点连起来最优,将这些边加入边集中。
  • 对于在同一个子树内的两个点 uv,这样连边的边权大于实际边权,但没有关系,这样肯定不优,而实际边权会在之后的递归中被考虑到,所以可以照样加进去。
  • 最后对于选出来的边跑一遍 Kruskal 即可。
  • 时间复杂度 O(nlog2n)

考虑将子问题的解法扩展到当前问题。

对第二棵树点分治,那么对于当前分治重心 x 来说,两个点 uv 的边权就是 d2(u,x)+d2(v,x)+d1(u,v)

x 这一层的所有节点在第一棵树上的虚树拿出来,并且对每一个点 u 建一个虚点 u+n,将它们俩连起来,边权为 d2(u,x)

对于虚树上的每一个点 u,找到离它最近的虚点 fru。对于每一条边 (u,v),如果离它们两个点最近的虚点不同,那么在最终边集中加入 (fru,frv,wu,v+disu+disv),其中 disu 表示 u 和与它最近的虚点的距离。对于最终边集跑一边 Kruskal 即可。

这样做为什么是对的?考虑加入到最终边集中的边边权一定不会小于实际边权(因为加进的边一定合法),对于最终最小生成树上的一条边 (u,v,w),当分治重心在 uv 的路径上时,这条边就会加入。

时间复杂度 O(nlog2n)

Code:https://pastebin.ubuntu.com/p/fN3Rbg5mHV/

posted @   csxsi  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2021-03-17 题解【JOI 2020/2021 二次予選】B - パンケーキ (Pancake)
2020-03-17 题解【洛谷P4025】[PA2014]Bohater
点击右上角即可分享
微信分享提示