BZOJ 1131 [POI2008]Sta(树形DP)
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1131
【题目大意】
给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大
【题解】
我们记dp[i]为所有点到i的深度之和,我们发现对于定根树,
dp[x]=dp[fx]+n-2*size[x],那么我们随意定根,先算出dp[root],
递归计算每个dp[x],对于计算每个节点的不同链时,回溯消除链上影响。
【代码】
#include <cstdio> #include <vector> using namespace std; const int N=1000010; typedef long long LL; vector<int> v[N]; int size[N],pos,n; LL ans,res; void dfs(int x,int d,int fx){ res+=d; size[x]=1; for(int i=0;i<v[x].size();i++)if(fx!=v[x][i]){ dfs(v[x][i],d+1,x); size[x]+=size[v[x][i]]; } } void dfs2(int x,int fx){ for(int i=0;i<v[x].size();i++)if(fx!=v[x][i]){ int y=v[x][i]; res=res+n-2*size[y]; if(res>ans||res==ans&&y<pos){ pos=y; ans=res; }dfs2(y,x); res=res-(n-2*size[y]); } } int main(){ while(~scanf("%d",&n)){ res=ans=0; for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); }dfs(1,0,0); ans=res;pos=1; dfs2(1,0); printf("%d\n",pos); }return 0; }
愿你出走半生,归来仍是少年