方法1:贪心
根据题目描述,很直观的可以想到一个贪心算法:
当k==1时选出树的直径(最长链),如图有一棵树:
图1的连接方式必定比图2更优
因此我们先找出树的直径,当k==1时直接得到答案。
对于k==2,此时我们已经有了一条直径,若把这条直径连成环,原树就变成了一个环套树,环套树还要合并任意两个结点,我们可以得到限制条件:
$\quad$①环越大越好
$\quad$②新环与原环相交部分越少越好
那么即可将第一次的到的环边权改为-1,再找一次最大的环,得到答案。
为什么这样是正确的?
因为将重叠部分重新添加了回去,故重叠部分对答案的影响消除了,同时满足了两个限制条件。
优化
我们发现找环并不必要。
因为我们添加的边不可能与另一个环相交。
故只需要找出直径并将直径上的边权改为-1,再重新求出直径即可。
方法2:树形动规
根据题目描述与数据范围,这题很难想到树形动规这一种解法。
考虑到上诉贪心做法,当两条直径相交时,减去相交部分,与选出两条不相交的直径等价(如图黑色的环与红色环等价)。
根据总结本P55树形动规的总结,树形动规可以找出树上的一个或多个图形。
首先列出所有的可能情况。(注:环链指差一条边成为环的链)
- 情况1
如图,即当前结点的所有后代中有两个环链。(规定必须是后代,不包含自己)
环链的求法和直径一样,即为当前结点最长链+次长链。
故维护最长链d1[]与次长链d2[]。
易得当前结点子树中环链的最大长度:故统计当前结点的子结点Circle[]的最大c1[]与次大c2[],使用$c1[i]+c2[i]$更新答案。 - 情况2
如图,即其中一个环链是另一个环链的祖先。(规定必须严格祖先后代关系,不能相交)
根据上图,选择箭头所指点统计答案较为便捷。
当前已经有了第一个环链(后代),但是要构成第二个环链(祖先),需要讨论环链如何构成。(注:du表示来自父亲的最长链)
$\quad$ ①
$\quad$ 如图,最长链与次长链均不来自环链,du+d1与d1+d2可以构成两个环链。
$\quad$ 使用$max(d2[Now],du[Now])+d1[Now]+Circle[Next]$更新答案。
$\quad$
$\quad$ ②
$\quad$ 如图,最长链来自环链(判断方法:d1[Next]+1==d1[Now]),那么有了环链,就不能使用d1+d2更新答案。
$\quad$ 为了构成祖先环链,我们还需维护第三长链d3[],那么du+d2与d2+d3可以构成两个环链。
$\quad$ 使用$max(d3[Now],du[Now])+d2[Now]+Circle[Next]$更新答案。
$\quad$
$\quad$ ⑨
$\quad$ 类似的,次长链来自环链(判断方法:d1[Next]+1==d2[Now]),不能使用d1+d2更新答案。
$\quad$ du+d2与d2+d3可以构成两个环链。
$\quad$ 使用$max(d3[Now],du[Now])+d1[Now]+Circle[Next]$更新答案。
$\quad$
那么情况2就讨论完了。 - 情况3
如图,两个环链有交点。(边不相交,点相交)
在交点处统计答案较为便捷。
故得到以下图形:
由图,还需要维护第四长链d4[]
显然可以使用$d1[Now]+d2[Now]+d3[Now]+max(d4[Now],du[Now])$更新答案
整理一下需要维护的信息
- d1[]~d4[]:最长链~第四长链
- du[]:来自父亲的最长链
- Circle[]:当前结点子树中环链的最大长度
- c1[]、c2[]:当前结点儿子的Circle值最大与次大
最后输出$2(n-1)-(ans2-ans-2)$即可。
至此,问题完美解决。
扩展:若求三个或k个环链怎么办?
若k为常数:继续讨论呗
否则:还是按照标准题解写吧。。。
代码
1 |
|