其实这个东西不依靠任何的顺序,如果你用 v_i 表示第 i 个儿子,之后将 siz[u] 拆成 i 之前的儿子的子树大小和,再进行拆式子,你会发现这个东西确确实实不论顺序,最后的总和是一样的。
然后我们考虑怎么换根。
我们设 dp[u] 表示以 u 为根的答案,v 是它的子节点。
然后就没有了。
代码如下。
```cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MN=1e6+116;
struct Node{
int nxt, to;
}node[MN];
int head[MN], tottt;
void insert(int u, int v){
node[++tottt].to=v;
node[tottt].nxt=head[u];
head[u]=tottt; return;
}
int n, f[MN], dp[MN], siz[MN], ans;
void dfs1(int u, int father){
siz[u]=1;
for(int i=head[u];i;i=node[i].nxt){
int v=node[i].to;
if(v==father) continue;
dfs1(v,u);
f[u]+=f[v]+siz[v]*(2*siz[u]-1);
siz[u]+=siz[v];
}
}
void dfs2(int u, int father){
for(int i=head[u];i;i=node[i].nxt){
int v=node[i].to;
if(v==father) continue;
dp[v]=dp[u]-n+2*siz[v]; ans=min(dp[v],ans);
dfs2(v,u);
}
}
signed main(){
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin>>n;
for(int i=1; i<n; ++i){
int u, v; cin>>u>>v;
insert(u,v); insert(v,u);
}
dfs1(1,0); ans=dp[1]=f[1];
dfs2(1,0); cout<<ans<<'\n';
return 0;
}
```