Loading

[每日 C] Remove Exactly Two

前言

做一下一场没打的 \(\textrm{div 2}\)\(\rm{C}\)

最近思维能力还在下降, 无敌
前天还能打出思维题, 今天打不出 \(\textrm{div 2 C}\)

思路

首先转化题意

给定一个 \(n\) 节点的树, 求删除两个节点及其连边之后, 最大连通块的数量

不难发现删除一个节点, 会把树分成几个部分, 由其出边条数确定
但是删除两个节点略有不同

容易想到的是贪心的切两次
考虑是否能够找到反例
容易发现大小为 \(4\) 的菊花图或者
pEEIKVs.png

都可以卡掉贪心做法

考虑贪心做法为什么是错的, 一般来说, 都是因为删除了一个点使得浪费了其他点的出边

所以现在问题简单化成了如何找到两个点, 使关于两个点的边数最大

方法 \(1\)

这个问题可以考虑树形 \(\rm{dp}\) , 因为边的重合不具有传递性或者后效性, 可以直接做
\(f_{u, 0/1/2, 0/1}\) 表示 \(u\) 子树, 删了多少个点, 其中 \(u\) 点是否被删除的最大联通块个数

考虑转移
初始化 \(f_{\textrm{leaves}, 0, 0} = 1, f_{\textrm{leaves}, 1, 1} = 0\)
转移不说了, 不难想到

方法 \(2\)

你发现可以不用这么高级, 直接 \(\rm{multiset}\) 维护删除每一个点之后余下点的度数, 不难发现是 \(\mathcal{O} (n \log n)\)

总结

善于找到问题的本质

这种树上问题可以考虑 \(\rm{dp}\) , 但是注意状态一定要能转移
然后就是之前做过的树上合并的问题了

posted @ 2025-01-26 20:48  Yorg  阅读(44)  评论(0编辑  收藏  举报