题解:P14671 [ICPC 2025 Seoul R] Clean Arrangement
性质:子树具有最优子结构性。
证明:考虑子树放到当前根
那么原问题转化为,当前
子树内部贡献不变,而其与
因此考虑从两边往中间放即可,使得越大的子树加的次数越少即可。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int now[N],pre[N],to[N],tot=0;
int n;
int siz[N],rk[N],dp[N];
void add(int x,int y){
tot++;
to[tot]=y;
pre[tot]=now[x];
now[x]=tot;
}
struct Node{
int siz,v;
}a[N];
int cnt=0;
bool cmp(Node A,Node B){
return A.siz>B.siz;
}
void dfs(int x,int f){
dp[x]=rk[x]=0;
siz[x]=1;
for(int i=now[x];i;i=pre[i]){
int node=to[i];
if(node==f) continue;
dfs(node,x);
siz[x]+=siz[node];
}
cnt=0;
for(int i=now[x];i;i=pre[i]){
int node=to[i];
if(node==f) continue;
a[++cnt]={siz[node],dp[node]+rk[node]};
}
sort(a+1,a+cnt+1,cmp);
for(int i=1;i<=cnt;i++){
if(i%2==1) dp[x]+=a[i].siz*((i-1)/2)+a[i].v;
else dp[x]+=a[i].siz*((i-1)/2)+a[i].v,rk[x]+=a[i].siz;
}
rk[x]++;
}
void solve(){
cin>>n;
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
dfs(1,0);
cout<<dp[1]<<endl;
}
int main(){
int T=1;
// scanf("%d",&T);
while(T--) solve();
return 0;
}