給定一棵無根樹,假設它有n個節點,節點編號從1到n, 求1-n這n個節點,到其他n-1個節點的距離之和。
Input
第一行包含一個正整數n (n <= 100000),表示節點個數。 後面(n - 1)行,每行兩個整數表示樹的邊。
Output
每行一個整數,第i(i = 1,2,…n)行表示所有節點到第i個點的距離之和。
Sample Input
4
1 2
3 2
4 2
Sample Output
5
3
5
5
思路:
換根dp。
第一次掃描得出節點1的值。
第二次掃描加上父節點的距離值,得到每個節點爲根的值。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
int siz[maxn],res[maxn];
int head[maxn],nex[maxn * 2],to[maxn * 2],tot;
ll f[maxn];
int n;
void add(int x,int y) {
to[++tot] = y;
nex[tot] = head[x];
head[x] = tot;
}
void dfs(int u,int fa) {
siz[u] = 1;
for(int i = head[u];i;i = nex[i]) {
int v = to[i];
if(v == fa) continue;
dfs(v,u);
siz[u] += siz[v];
f[u] += siz[v] + f[v];
}
}
void dfs2(int u,int fa) {
for(int i = head[u];i;i = nex[i]) {
int v = to[i];
if(v == fa) continue;
ll num = f[u] - siz[v] - f[v];
f[v] += (n - siz[v]) + num;
dfs2(v,u);
}
}
int main() {
scanf("%d",&n);
for(int i = 1;i < n;i++) {
int x,y;scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs(1,-1);
dfs2(1,-1);
for(int i = 1;i <= n;i++) {
printf("%lld\n",f[i]);
}
return 0;
}