这是一个树形dp的思想,两次dfs。
第一次dfs处理出,对于每个u,其所有子孙节点到其的距离之和。
第二次dfs处理出,对于每个u,所有点到其距离之和。
#include<iostream> #include<string.h> #include<string> #include<algorithm> #include<stdio.h> #include<vector> #include<set> #include<time.h> #define LL long long int using namespace std; const int maxn = 120000; vector<int> G[maxn]; LL sum[maxn]; LL sz[maxn]; LL save[maxn]; int n; void init() { memset(G,0,sizeof(G)); memset(sum,0,sizeof(sum)); memset(sz,0,sizeof(sz)); memset(save,0,sizeof(save)); } LL dfs_1(int u,int fa) { LL ans = 0; sz[u] = 1; for(int i = 0;i<G[u].size();i++) { int v = G[u][i]; if(v == fa) continue; ans += dfs_1(v,u); ans += sz[v]; sz[u] += sz[v]; } sum[u] = ans; return ans; } void dfs_2(int u,int fa,LL up) { save[u] = sum[u] + up; for(int i = 0;i<G[u].size();i++) { int v = G[u][i]; if(v == fa) continue; dfs_2(v,u,up + n - sz[u] + sum[u] - sum[v] - sz[v] + sz[u] - sz[v]); /* next up = up + (n - sz[u]) + (sum[u] - sum[v] - sz[v]) + sz[u] - sz[v]; up是原来的up,肯定要加 对于u以上的所有节点,相当于所有的节点到他的距离+1,所以有n - sz[u] 对于u的子树,sum[u] - sum[v] - sz[v]是指(除了v以外的,其他子树的所有节点到u的距离和) sz[u] - sz[v]是紧接着上一条的,因为u到v又推进了一条边,所以需要加一次长度 */ } } int main() { while(cin >> n) { init(); for(int i = 0;i<n-1;i++) { int u,v; scanf("%d %d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs_1(1,-1); dfs_2(1,-1,0); for(int i = 1;i<=n;i++) { printf("%lld\n",save[i]); } } return 0; }