【UR #7 C】水题走四方(DP)
水题走四方
题目链接:UR #7 C
题目大意
给你一棵有根树,有两个人一开始都在根节点。
然后每个人每个时刻可以不动或者走到一个儿子,然后两个人可以不花费时间的把一个人传送到另一个人的位置。
然后问你两个人合起来访问所有点的最小时间是多少。
思路
首先思考一下为啥一定可以走完。
不难想象到就是一个人可以固定在根节点,然后让另一个人走就可以。
于是考虑优化这个过程。
发现如果走剩两个儿子,然后其中一个儿子没走的部分构成一条链,那我们可以让两个人分别走一个儿子,然后构成链的儿子走到底再传回另一个人那边。
那两个人要做的事是可以交换的,所以我们固定一个人给另一个人传,分别称为本人和分身。
那本人走的就是一条链,我们考虑根据这条链来 DP。
但是本人的这条链它不是每个点都会停下来,我们就不能直接 去 DP。
于是考虑会从那些点转移:
其实会发现如果有多个,肯定是能停就停,这是一个显然的,因为走的都是同一段。
所以我们应该要问的是从哪个点转移。
考虑找,其实就是看要不要等,那你看看等的条件。
其实很显然,就是它除了你这个点挂着的儿子的子树,要有一个儿子的最深深度不小于你。
这样最后它在那走,你走到这里,就要等他走完传到你这里。
我们把转移的位置叫做 。
所以呢,我们就可以有一个方法找,我们把当前还没有找到的弄出来,可以直接用类似链表存。(因为你找到的肯定是前面的一段)
然后每次你合并一个子树,你就看两个:其它子树会不会因为它有了 ,它会不会从其它子树得到 。
然后条件就是 ( 是你链表枚举的点, 是判断的点,如果是其它子树就是父亲点,否则是儿子点)
然后考虑怎么合并,两条合一起似乎不太可能,好像不能用链表了。
但是会发现其实一定只会有一条链,因为它这个是找最长的链给贡献,但是最长的至少一个,那如果是最长的一定会全部删完,两边里面肯定至少有一遍有最大的。
所以我们直接把它的下一个接到有的那个即可,没有就不接。
因为每次是准确找 ,找不到就走,所以是 的。
接下来就是愉快的 DP 了!
首先是跟 的转移,就直接把 的子树中不是 这个的子树的加上。
(维护子树大小,每个点的深度,子树深度和即可)
然后其实不难想象会出现没有 的情况,比如只有一个儿子。(注意是父亲只有它这个儿子)
那我们考虑只能从父亲那里过来,所以也可能是 。(当然一定要没有 才行)
然后对于叶子节点我们更新一下答案,就可以啦!
代码
__EOF__

本文链接:https://www.cnblogs.com/Sakura-TJH/p/UR_7_C.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现