链接:点击打开链接
题意:给定一棵无根树,假设它有n个节点,节点编号从1到n, 求任意两点之间的距离(最短路径)之和
代码:
#pragma comment(linker, "/STACK:102400000,102400000")
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
const long long SIZE=100005;
long long n,dp[SIZE],num[SIZE],used[SIZE];
vector<long long> G[SIZE];
void dfs1(long long s,long long sum){
long long i,tmp;
dp[1]+=sum; //以1为根节点算出根节点
used[s]=1; //到所有节点的和
for(i=0;i<G[s].size();i++){
tmp=G[s][i];
if(G[tmp].size()&&!used[tmp]){
dfs1(tmp,sum+1);
num[s]+=num[tmp]; //求出每个节点包括自己所
} //含的子树中节点的总数
}
}
void dfs2(long long s){
long long i,tmp;
used[s]=1;
for(i=0;i<G[s].size();i++){
tmp=G[s][i];
if(!used[tmp]){ //当前节点到其他节点的路径
dp[tmp]+=(dp[s]+(n-num[tmp])-num[tmp]); //和,可由父节点的节点数和
dfs2(tmp); //当前节点的节点数所推导出来
}
}
}
int main(){
long long a,b,i;
while(scanf("%I64d",&n)!=EOF){
for(i=1;i<=n;i++)
G[i].clear();
fill(num,num+n+1,1);
memset(dp,0,sizeof(dp));
memset(used,0,sizeof(used));
for(i=0;i<n-1;i++){
scanf("%I64d%I64d",&a,&b); //因为是无向边
G[a].push_back(b);
G[b].push_back(a);
}
dfs1(1,0);
memset(used,0,sizeof(used));
dfs2(1);
for(i=1;i<=n;i++)
printf("%I64d\n",dp[i]);
}
return 0;
}