首先回顾一下关于图论的几个概念。树是图的一种,是指没有回路的连通图。对于这种图,任意一个节点都可以当做root从而展开为一棵直观意义上的树。
本题中我们可以任意选取一个节点定义为root(比如说0号节点),然后可以用DFS遍历整棵树,可以得到两个信息:每个节点所对应的子树的节点个数(记做count[i]),所有节点到根(0号节点)的距离之和。
那么接下来,如何得到一个非根节点到其他所有节点的距离之和呢?难道要以该节点为根重新展开一张树吗?这里介绍一种非常常见的“移根”的思想。
我们令f(node)该节点到所有节点的距离之和。假设已知f(parent),我们可以考虑f(parent)和它的一个f(child)之间的关系。我们把根从parent迁到child之后,所有属于child子树的节点离根的距离都减少了1。剩余的其他所有节点,其到根的距离都增加了1.
所以有如下的关系
f(child) = f(parent) - (child子树的节点数目) + (N - child子树的节点数目)
可见,所有的f都可以自上而下通过递归得到。
类似的思想有一个更常见的题目:求一个数组里每个节点到其他节点的距离之和。如1685,2121.