51nod1405(树形dp)

来源:互联网 发布:c语言比较三个数大小 编辑:程序博客网 时间:2024/06/05 04:37

链接:点击打开链接

题意:给定一棵无根树,假设它有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;}


 

0 0