您的位置:首页 > 其它

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

2016-09-04 13:32 483 查看

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 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: