学习心得 - 动态规划 - 换根 DP
题目
求树上一个点到其他点距离之和模 \(10^9+7\)。
即设 \(\operatorname{dis}(u,v)\) 为两点距离,求 \(f_u=\sum_{v=1}^n \operatorname{dis}(u,v) \bmod 10^9+7\)。
\(1\leq n\leq 10^5\)。
举例

我们首先用一个大家都会的方法处理出 \(f_1\) 的答案。
考虑用 \(sz\) 维护一个点的子树大小。
这时就可以推出 \(f_p=\sum(sz_v +f_v)\)(子树答案全体贡献 \(+1\))
接下来我们要试图通过 \(f_1\) 求出其他的答案。
我们先把根换做 \(2\):

我们发现:

部分节点的贡献发生了变化!
注意到 \(-1\) 部分的是原来 \(2\) 节点的子树。
而其他的点贡献全部 \(+1\)。
那么,我们就得出:\(f_v=f_p-sz_p+(n-sz_p)\)。
化简得 \(f_v=f_p-2\times sz_p+n\)。
代码
int sz[N];
ll f[N];
vector<int>e[N];
void dfs(int p,int fa){
sz[p]=1;
for(auto v:e[p])if(v!=fa){
dep[v]=dep[p]+1;
dfs(v,p);
(f[p]+=sz[v]+f[v])%=P;
sz[p]+=sz[v];
}
}
void dfs2(int p,int fa){
for(auto v:e[p])if(v!=fa){
f[v]=(f[p]-2*sz[v]+n)%P;
dfs2(v,p);
}
}
第一次求 \(f_1\),\(sz\),第二次求 \(f_{2\dots n}\)。

浙公网安备 33010602011771号