换根dp

引入

Problem

现在有一个无根树,要你确定一个根,使得其他点到这个根的距离最短。\(n \le 10^5\)

Solution

Thinking 1

枚举根,dfs暴力求距离,取最大值,时间复杂度\(\mathcal{O}(n^2)\)

Thinking 2

如果让根的子树变成根,那个树的形态其实很多都没变!如果再来一次\(\mathcal{O}(n)\)的话,太浪费了!
我们考虑先选一个根节点(默认为1),然后dfs子树来更新。


假设我们现在已经通过第一次dfs算出了\(dp[1]\)(以1为根的答案),来求\(dp[2]\)。不难发现,\(2\)\(A\)的深度都相比一开始减1,那么对答案的贡献就是减子树的大小,即\(siz[2]\),然后除了\(2\)\(A\)以外的所有点深度都加1,对答案的贡献加\(n - siz[2]\)
整理得

\[dp[2] = dp[1] - siz[2] + n - siz[2] = dp[1] + n - 2siz[2] \]

推广到一般形式:

\[dp[v] = dp[x] + n - 2siz[v] \]

不难发现只需要两次dfs,所以时间复杂度为\(\mathcal{O}(n)\)

做法

1.先定一个根(一般是1),然后先算出答案,同时预处理一些转移需要的东西。
2.根据具体题目推式子转移。

Exercise

Simple:

Normal:

posted @ 2021-06-19 11:15  luyiming123  阅读(62)  评论(3编辑  收藏  举报