51nod 1405 树的距离之和

给定一棵无根树,假设它有 n 个节点,节点编号从 1 n , 对于每个点,求这个点到其他所有点距离的和。

Input

第一行包含一个正整数 n(n100000),表示节点个数。
后面 (n1) 行,每行两个整数表示树的边。

Output

每行一个整数,第 i(i=1,2,...n) 行表示所有节点到第i个点的距离之和。

Solve

见下图, v u 的儿子。

x v 的子孙, y 过其他点(注意 y 不一定是 u 的子孙,也可能是祖先)。

fig.1

fu 表示对 u 点要求的答案。按照上图有:

fufv===xd(x,u)+yd(y,u)+1xd(x,v)+yd(y,v)+1x[d(x,u)1]+y[d(y,u)+1]+1

比较之后发现 fv=fucntx+cnty 。这里 cntx 表示 x 遍历的点数,同理有 cnty

cntx 就是 v 的子孙数目,而 cnty=n2cntx 。那么就有 fv=fu+[n2(cntx+1)] cntx+1 v 为根的树的节点数。是可以计算的。

现在我们由一个节点的 f 可以计算出其儿子的 f 。为此,我们计算 froot (容易),然后再次递归就可以计算每个点的答案。

本题数据严格,最后一组数据(截至2016-02-16)是 100000 个点组成的一条链,这样的数据用递归形式写是会爆栈的。手工扩栈其实也不保险。可以用模拟栈非递归的进行计算。

https://code.csdn.net/qq_23020601/acm/blob/master/51NOD/1405.cpp

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值