思路:
如果是求根为1的点,整棵树的深度和,我们可以用一次dfs来统计每个节点的深度。
现在考虑换根:我们发现现在的根2的子树及2本身的深度都减1,其余点的深度都加1。
那么我们不仅需要统计每个点的深度,而且要统计每个节点子节点的数量cnti,再需要一次dfs。
然后最后一次dfs是dp的过程,考虑对于换根点v,其原来父节点为u,那么dpv=f[u]-cnt[i]+(n-cnt[i])。
最后求所有的dpi的最小值。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define LL long long
#define INF 0x3f3f3f3f3f
using namespace std;
int dx[10] = { -1,1,0,0 };
int dy[10] = { 0,0,-1,1 };
const int maxn = 1000000 + 10;
int head[maxn<<1];
struct node
{
int next,to;
}a[maxn<<1];
int cnt1;
void add(int u,int v)
{
cnt1++;
a[cnt1].to=v;
a[cnt1].next=head[u];
head[u]=cnt1;
}
int n;
int dep[maxn];
int cnt[maxn];
LL dp[maxn];
void dfs1(int u,int fa)
{
for(int i=head[u];i;i=a[i].next)
{
int v=a[i].to;
if(v==fa)continue;
dep[v]=dep[u]+1;
dfs1(v,u);
}
}
void dfs2(int u,int fa)
{
for(int i=head[u];i;i=a[i].next)
{
int v=a[i].to;
if(v==fa)continue;
dfs2(v,u);
cnt[u]+=cnt[v];
}
}
void dfs3(int u,int fa)
{
for(int i=head[u];i;i=a[i].next)
{
int v=a[i].to;
if(v==fa)continue;
dp[v]=dp[u]-cnt[v]+n-cnt[v];
dfs3(v,u);
}
}
int main()
{
scanf("%d",&n);
rep(i,1,n-1)
{
int u,v;
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
}
//求dep
dfs1(1,0);
rep(i,1,n)cnt[i]=1;
dfs2(1,0);//求cnt
for(int i=1;i<=n;i++)
{
dp[1]+=dep[i];
}
dfs3(1,0);
LL minn=INF;
for(int i=1;i<=n;i++)
{
minn=min(minn,dp[i]);
}
printf("%lld\n",minn);
}