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 ; }
相关文章推荐
- 51nod 1405 树的距离之和【树型dp】
- 51nod 1405 树的距离之和(DFS)
- 51Nod 1405 树的距离之和 (树dp)
- 51nod 1405 树的距离之和【树形dp】
- 51nod 1405 树的距离和
- 51nod 1405 树的距离之和
- 51nod 1405 树的距离之和 【dfs--记忆dp??树形dp??】
- 51nod 1405 树的距离之和(DP)
- 51nod-1405 树的距离之和
- 51nod 1405 树的距离之和
- 51nod 1405 树的距离之和 (树形dp)
- 51Nod 1405 树的距离之和(dp)
- 51nod 1405 树的距离之和
- 51Nod 1405 树的距离之和(dp)
- 51nod 1405 树的距离之和
- 51nod 1405 树的距离之和
- 51nod 1405 树的距离之和 (两次dfs,树形dp)
- 51nod 1405 树的距离之和
- 51Nod 1405 树的距离之和(树形dp)
- 51nod 1405 树的距离之和 (两次dfs,树形dp)