51nod 1405 树的距离之和 (两次dfs,树形dp)

来源:互联网 发布:软件版本升级说明 编辑:程序博客网 时间:2024/06/05 03:24


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


#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <cstdlib>#include <vector>#pragma comment(linker, "/STACK:10240000,10240000")//递归太深,导致爆栈,所以使用扩栈语句using namespace std;typedef long long ll;const int N = 100000 + 5;vector<int>vv[N];int num[N],n;ll dp[N];int dfs(int u,int pre,int d){int len=vv[u].size();num[u]=1;dp[1]+=d;for(int i=0;i<len;i++) {if(vv[u][i]==pre) continue;num[u]+=dfs(vv[u][i],u,d+1);}return num[u];}void dfs2(int pre,int u){dp[u]=dp[pre]+n-2*num[u];int len=vv[u].size();for(int i=0;i<len;i++) {if(vv[u][i]==pre) continue;dfs2(u,vv[u][i]);}}int main(){int i,j,u,v;scanf("%d",&n);for(i=1;i<n;i++) {scanf("%d%d",&u,&v);vv[u].push_back(v);vv[v].push_back(u);}dfs(1,0,0);for(i=0;i<vv[1].size();i++) {dfs2(1,vv[1][i]);}for(i=1;i<=n;i++) printf("%I64d\n",dp[i]);return 0;}



0 0