51nod 1405 树的距离之和(树型dp)

来源:互联网 发布:淘宝钻展在哪里展示 编辑:程序博客网 时间:2024/04/28 04:53

51nod 1405

题目

中文题目

思路

考虑还是不能一个个点去思考,而是看边与所求的关系,还是菜菜的。
num[i]记录i有多少个子节点,dp[i]表示所有点到i的距离和,dep[i]表示i的深度,结点u,对于它的子节点x,x的子节点到x的距离比到u的距离少1,除了x,u以外的点到x的距离比到u的距离多一,所以dp[x]=dp[u]-num[x]-(n-2-num[x]),根节点根据深度就可以求出,然后就可以求出所有。

代码

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <cmath>#include <iostream>using namespace std ;typedef long long ll;const int maxn=100010;int tot,head[maxn],n;struct node{    int next;    int to;} edge[maxn*2];void addedge(int from,int to){    edge[tot].to=to;    edge[tot].next=head[from];    head[from]=tot++;}int num[maxn],dep[maxn];ll dp[maxn],tol;void dfs1(int u,int fa,int depth){    num[u]=0;    dep[u]=depth;    tol+=dep[u];    for(int i=head[u]; ~i; i=edge[i].next)    {        int v=edge[i].to;        if(v==fa) continue;        dfs1(v,u,depth+1);        num[u]+=num[v]+1;    }}void dfs2(int u,int fa){    for(int i=head[u]; ~i; i=edge[i].next)    {        int v=edge[i].to;        if(v==fa) continue;        dp[v]=dp[u]+n-2-2*num[v];        dfs2(v,u);    }}int main(){    scanf("%d",&n);    tot=0;    tol=0;    memset(head,-1,sizeof(head));    for(int i=1; i<n; i++)    {        int a,b;        scanf("%d %d",&a,&b);        addedge(a,b);        addedge(b,a);    }    dfs1(1,-1,0);    dp[1]=tol;    dfs2(1,-1);    for(int i=1; i<=n; i++)        printf("%I64d\n",dp[i]);    return 0 ;}
0 0
原创粉丝点击