樹的距離之和 51Nod - 1405(換根dp)

給定一棵無根樹,假設它有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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章