题目:https://hihocoder.com/contest/offers59/problem/3
其实就是一个树的转移中心的题。
以1为根节点做一遍dfs可以得到1到其他所有点 的距离之和。
求某点到其他点的距离之和的时候可以根据最初的情况转移。
比如设点k是点1的子节点,w[k]=w[1]-cnt[k]+n-cnt[k],其中cnt[k]是k的子树的节点个数(包括k本身)。当根节点由一个点转移到它的子节点k时,k到其子节点的距离均-1,到其他点的距离均+1。
贴代码
#include <bits/stdc++.h>
#define LL long long
using namespace std;
vector<vector<int> >edge;
vector<LL>cnt;
vector<LL>ans;
LL W=0;
int n;
void dfs1(int u,int f,LL d){
cnt[u]=1;
W+=d;
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i];
if(v==f)
continue;
dfs1(v,u,d+1);
cnt[u]+=cnt[v];
}
}
void dfs2(int u,int f,int w){
ans[u]=w;
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i];
if(v==f)
continue;
dfs2(v,u,w-cnt[v]+n-cnt[v]);
}
}
int main(){
scanf("%d",&n);
edge.resize(n+1);
cnt.resize(n+1);
ans.resize(n+1);
int u,v;
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
edge[u].push_back(v);
edge[v].push_back(u);
}
dfs1(1,1,0);
dfs2(1,1,W);
for(int i=1;i<=n;i++)
printf("%lld\n",ans[i]);
return 0;
}