1405 树的距离之和
基准时间限制:1 秒 空间限制:131072 KB
给定一棵无根树,假设它有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
思路:我们可以先一遍dfs求出每个节点到他的所有子节点的距离和,那么根节点存的就是他到树上每个节点的
距离和,这样根节点的儿子就可以由他转移过来,就可以求出题目要求的答案来.
代码:
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5+5;
struct node
{
int u,v,ne;
} e[maxn];
int n;
int head[maxn],len;
int ve[maxn];
ll d[maxn];
void add(int u,int v)
{
e[len].u = u;
e[len].v = v;
e[len].ne = head[u];
head[u] = len++;
}
void dfs(int x,int p)
{
ve[x] = 1;
for(int i = head[x];~i;i = e[i].ne)
{
int v = e[i].v;
if(v == p) continue;
dfs(v,x);
d[x]+= d[v]+ve[v];
ve[x]+= ve[v];
}
return ;
}
void dfs2(int x,int p)
{
for(int i = head[x];i!= -1;i = e[i].ne)
{
int v = e[i].v;
if(v == p) continue;
d[v]+= d[x]-d[v]-ve[v]+n-ve[v];
dfs2(v,x);
}
return ;
}
int main()
{
mem(head,-1);
cin>>n;
for(int i = 1,x,y;i< n;i++)
{
scanf("%d %d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1,0);
dfs2(1,0);
for(int i = 1;i<= n;i++)
printf("%lld\n",d[i]);
return 0;
}