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
",pos);
    }return 0;
}
原文地址:https://www.cnblogs.com/forever97/p/bzoj1131.html