P3478 [POI2008] STA-Station


题面

给定一个 \(n\) 个点的树,请求出一个结点,使得以这个结点为根时,所有结点的深度之和最大。

一个结点的深度之定义为该节点到根的简单路径上边的数量。

分析

本题可以用树形DP做。

首先,把树按照链式前向星的方法保存。

然后考虑第 \(i\) 个点的深度来DP,先求 \(DP_1\),然后往下推,深度减小了 \(size_v\),增加了 \(n-size_v\)。所以用 \(O(n)\) 的算法来DP,然后直接用 \(O(n)\) 统计最大值。

贴上代码

#include
using namespace std;

const int N = 1e6+10;
struct Edge{
	int next,to;
} e[N<<1];

int deep[N],head[N],length;
int siz[N];
long long dp[N];
int n,a,b;
int result=0;

void add(int u,int v){
	e[++length].to=v;
	e[length].next=head[u];
	head[u]=length;
}

void dymanic_planning(int u,int fa){
	siz[u]=1;
	dp[u]=deep[u];
	for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa)continue;
        deep[v]=deep[u]+1;
        dymanic_planning(v,u);
        siz[u]+=siz[v];
        dp[u]+=dp[v];
    }
}

void solve(int u,int fa){
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa)continue;
        dp[v]=dp[u]-siz[v]+n-siz[v];
        solve(v,u);
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
	cin>>n;
	for(int i=0;i>a>>b;
		add(a,b);
		add(b,a);
	}
	dymanic_planning(1,0);
	solve(1,0);
	for(int i=1;i<=n;i++){
		if(dp[result]