51nod 1405 树的距离之和 搜索+DP

给定一棵无根树,假设它有n个节点,节点编号从1到n, 求任意两点之间的距离(最短路径)之和。
Input
第一行包含一个正整数n (n <= 100000),表示节点个数。
后面(n - 1)行,每行两个整数表示树的边。
Output
每行一个整数,第i(i = 1,2,...n)行表示所有节点到第i个点的距离之和。
Input示例
4
1 2
3 2
4 2
Output示例
5
3
5

5

假设以第一个点为根节点,我们开始搜索,记录以当前节点的深度以及当前节点的子节点个数。

之后对于统计。

对于X节点,我们已经知道他的距离之和为dp【X】了。

那么他的子节点Y节点。

dp【Y】=dp[X] - num[y] + n - num[y]

解释一下:其他点到达y,有两种情况。第一种点在y节点的子树上。 也就是num【y】个,这num【y】个点

到达y要比到达x小1. 所以dp【x】-num【y】. 第二种情况,不在y的子树上的点,也就是n-num【y】个,

他们要比到达x多1.所以在原来的基础上再加上n - num[y]。

那么我们dfs来求dp即可。

#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<iostream> using namespace std; vector<long long>p[100010]; bool f[100010];//是否访问过 long long dp[100010];//当前深度到S的深度 long long num[100010];//子节点数量 long long n; void dfs(long long s,long long depth) {     long long len=p[s].size();     f[s]=1;     num[s]=1;     dp[1]+=depth;     for(long long i=0;i<len;i++)     {         if(!f[p[s][i]])         {             dfs(p[s][i],depth+1);             num[s]+=num[p[s][i]];         }     } } void solve(long long s) {     long long len=p[s].size();     f[s]=1;     for(long long i=0;i<len;i++)     {         if(!f[p[s][i]])         {             dp[p[s][i]]=dp[s]+n-num[p[s][i]]*2;             solve(p[s][i]);         }     } } int main() {     cin>>n;     for(long long i=2;i<=n;i++)     {         long long a,b;         cin>>a>>b;         p[a].push_back(b);         p[b].push_back(a);     }     dfs(1,0);     memset(f,0,sizeof(f));     solve(1);     for(long long i=1;i<=n;i++)         cout<<dp[i]<<endl; }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值