/* 拼接思想: g[u][j]表示u子树里距离u距离>=j的所有点都被覆盖的代价(子树里扣掉一个以u为圆心的扇形) g[u][j]=sum{g[v][j-1]} f[u][j]表示u子树内以及距离u距离<=j的所有点都被覆盖的代价 (子树加上以u为圆心的圆) f[u][j]=min(f[v][j+1]-g[v][j],j)+g[u][j+1] 这两个数组不能独立求,因为g[u][0]是由f[u][0]决定 */ #include<bits/stdc++.h> using namespace std; #define N 5005 vector<int>G[N]; int n,f[N][N],g[N][N],d[N]; void dfs(int u,int pre){ for(auto v:G[u]) if(v!=pre)dfs(v,u); for(int i=1;i<=n;i++) for(auto v:G[u]){ if(v==pre)continue; g[u][i]+=g[v][i-1]; } f[u][n]=n;//给f[u]顶一个初始状态 for(int i=n-1;i>=0;i--){ f[u][i]=max(1,i)+g[u][max(1,i)+1];//在u处放基站的代价 f[u][i]=min(f[u][i],f[u][i+1]);//和之前的比较 for(auto v:G[u]){ if(v==pre)continue; f[u][i]=min(f[u][i],f[v][i+1]-g[v][i]+g[u][i+1]); } } g[u][0]=f[u][0];//g[u]真正的初始状态 for(int i=1;i<=n;i++)//贪心的扫一下g[u] g[u][i]=min(g[u][i],g[u][i-1]); } int main(){ cin>>n; for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs(1,1); cout<<f[1][0]<<' '; }