hihocoder 1742 树的权重(51Nod-1405 树的距离之和)(树形DP)

描述

给定一棵包含N个节点的树,节点编号1~N。  

请你对于每一个节点,计算它到所有其他节点的距离之和。(每条边的长度为1)

输入

第一行包含一个整数N。  

以下N-1行,每行包含两个整数a和b,代表ab之间有一条边。  

对于30%的数据,1 ≤ N ≤ 1000  

对于100%的数据,1 ≤ N ≤ 100000

输出

输出N行,依次对于1~N号节点输出答案。

样例输入
4  
1 2  
2 3  
2 4
样例输出
5  
3  
5  
5

题意不用说了,直接说思路。先选定节点1作为树的根,然后用num[i]表示以节点i为根的子树上的节点数(包括i)。

dp[x]表示节点x到其他所有节点距离之和,设节点x是节点xx的父节点。

那么我们可以得到dp[xx] = dp[x] + (n-num[xx]) - num[xx]。

因为在xx子树上的节点到xx的距离要比到父节点x的距离要少1,所以减去1,一共有num[xx]个,所以减去num[xx]

不在xx子树上的节点到xx的距离要比到父节点x的距离要多1,所以加上n - num[xx]。

这样我们首先一个dfs处理出dp[1]的大小,就可以推出其他的大小。


#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long

using namespace std;

const int N = 1000010;

int n;
LL dp[N];
int vis[N];
int num[N];
vector<int> e[N];

void dfs(int x,int s)
{
    vis[x] = 1;
    num[x] = 1;
    dp[1] += s;
    for(int i=0;i<e[x].size();i++)
    {
        int xx = e[x][i];
        if(vis[xx] == 0)
        {
            dfs(xx,s+1);
            num[x] += num[xx];
        }
    }
}

void init_dp(int x)
{
    vis[x] = 1;
    for(int i=0;i<e[x].size();i++)
    {
        int xx = e[x][i];
        if(vis[xx] == 0)
        {
            dp[xx] = dp[x] + (n-num[xx]) - num[xx];
            init_dp(xx);
        }
    }
}
int main(void)
{
    int i,j;
    while(scanf("%d",&n)==1)
    {
        for(i=1;i<=n;i++)
            e[i].clear();
        for(i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            e[x].push_back(y);
            e[y].push_back(x);
        }
        dp[1] = 0;
        memset(vis,0,sizeof(vis));
        dfs(1,0);
        memset(vis,0,sizeof(vis));
        init_dp(1);
        for(i=1;i<=n;i++)
            printf("%d\n",dp[i]);
    }

    return 0;
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值