P3478 [POI2008] STA-Station
题面
给定一个 \(n\) 个点的树,请求出一个结点,使得以这个结点为根时,所有结点的深度之和最大。
一个结点的深度之定义为该节点到根的简单路径上边的数量。
分析
本题可以用树形DP做。
首先,把树按照链式前向星的方法保存。
然后考虑第 \(i\) 个点的深度来DP,先求 \(DP_1\),然后往下推,深度减小了 \(size_v\),增加了 \(n-size_v\)。所以用 \(O(n)\) 的算法来DP,然后直接用 \(O(n)\) 统计最大值。
贴上代码
#include<bits/stdc++.h>
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<n-1;i++){
cin>>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]<dp[i]){
result=i;
}
}cout<<result<<endl;
return 0;
}