1405 树的距离之和(51nod)

给定一棵无根树,求所有节点到其他节点的距离之和。采用两次DFS,第一次计算根节点到所有节点的距离和及子节点大小,第二次根据子节点大小计算每个节点到所有节点的距离和。状态转移方程为f[j]=f[i]+n-size[j]*2。
摘要由CSDN通过智能技术生成

1405 树的距离之和(51nod)

题面:给定一棵无根树,假设它有n个节点,节点编号从1到n, 求1-n这n个节点,到其他n-1个节点的距离之和。
传送门
输入:
第一行包含一个正整数n (n <= 100000),表示节点个数。
后面(n - 1)行,每行两个整数表示树的边。

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

这题其实挺水的 但还是想了一会
蒟蒻就用了递推,感觉好像第二个dfs有点dp的味道 emmm

思路:一看就不能暴力。因为是个无根树,所以随便拿一个点来当根都行。(本人比较习惯用1)开个数组size记录每个节点和它子节点集合的大小,开个sum用来记录dfs过程中从根节点到子节点的距离,也就是距离前缀和,f用来记录每个节点到其他所有节点的距离。

第一次:dfs我们可以从根节点向下求根节点到每个子节点的前缀和,用sum记录然后我们把每个节点的sum给了f[1]就求出根节点到所有节点的距离和了。同时回溯时,求出每个节点子集的大小,用size记录。

第二次dfs:已知根节点1到其他节点的距离和,然后还已知每个节点子集的大小,就可以用这玩意求出来f[j]=f[i]+n-2*size[j];

对于遍历到的任意一个节点 i,对于与之相邻的节点 j 来说,答案贡献由 i 到 j 转移首先减小了 size[j]

同时增加了 (n−size[j])(除了size[j]以外的点)因此可以直接得到状态转移方程f[j]=f[i]+n−size[j]∗2
在这里插入图片描述

如图,如果根转移到节点2,距离首先要减少size[2]*1,然后要增加(n-size[2])*1,因为根变为节点2,节点一到节点二子集的所有距离要消失,也就是红色部分(size[v]),要增加从节点2到节点一子集的距离也就是绿色部分(n-size[v])

话不多说,上代码

#include<bits/stdc++.h>
#define cn getchar 
#define ll long long 
using namespace std;

void in(int &x){
   
	int f1=1;char ch=cn();x=0;
	while(ch
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值