/*
拼接思想:
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]<<'\n';
}