#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <cassert>
#include <ctime>
#include <string>
#include <queue>

using namespace std;

#ifdef _WIN32
#define LLD "%I64d"
#else
#define LLD "%lld"
#endif

typedef long double ld;

long long rdtsc() {
  long long tmp;
  asm("rdtsc" : "=A"(tmp));
  return tmp;
}

inline int myrand() {
  return abs((rand() << 15) ^ rand());
}

inline int rnd(int x) {
  return myrand() % x;
}

#define pb push_back
#define mp make_pair
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#define sz(x) ((int)(x).size())
#define TASKNAME "text"

const int INF = (int) 1.01e9;
const ld EPS = 1e-9;

void precalc() {
}

const int maxn = 5000 + 10;

int n;
vector<vector<int> > es;

bool read() {
  if (scanf("%d", &n) < 1) {
    return 0;
  }
  es = vector<vector<int> >(n);
  for (int i = 0; i < n - 1; ++i) {
    int s, t;
    scanf("%d%d", &s, &t);
    --s, --t;
    es[s].pb(t), es[t].pb(s);
  }
  return 1;
}

int used[maxn];
int cnts[maxn];

int dp[maxn][maxn];

int tmp[maxn];

void dfs(int v) {
  used[v] = 1;

  cnts[v] = 0;
  dp[v][0] = 0;
  if (sz(es[v]) == 1) {
    ++cnts[v];
    dp[v][0] = INF;
    dp[v][1] = 0;
  }
  for (int it = 0; it < sz(es[v]); ++it) {
    int u = es[v][it];
    if (used[u]) {
      continue;
    }
    dfs(u);
    int cnt = cnts[v];
    for (int x = 0; x <= cnt; ++x) {
      tmp[x] = dp[v][x];
    }
    cnts[v] += cnts[u];
    for (int x = 0; x <= cnts[v]; ++x) {
      dp[v][x] = INF;
    }
    for (int xt = 0; xt <= cnt; ++xt) {
      for (int xu = 0; xu <= cnts[u]; ++xu) {
        int &cur = dp[v][xt + xu];
        cur = min(cur, tmp[xt] + min(dp[u][xu], 1 + dp[u][cnts[u] - xu]));
      }
    }
  }
}

void solve() {
  for (int i = 0; i < n; ++i) {
    used[i] = 0;
  }
  dfs(0);
  printf("%d\n", dp[0][cnts[0] / 2]);
}

int main() {
  srand(rdtsc());
#ifdef DEBUG
  freopen(TASKNAME".out", "w", stdout);
  assert(freopen(TASKNAME".in", "r", stdin));
#endif

  precalc();
  while (1) {
    if (!read()) {
      break;
    }
    solve();
#ifdef DEBUG
    eprintf("Time: %.18lf\n", (double)clock() / CLOCKS_PER_SEC);
#endif
  }
  return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define forn(i,n) for (int i = 0; i < n; i++)

using namespace std;

typedef long long ll;

const int N = 5123;
const short INF = 10000;
int n;
vector<int> g[N];

short z1[2][N][N];
short z2[2][N][N];
int leaves[N];

void dfs(int v, int p = -1) {
    if (g[v].size() == 1) {
        leaves[v] = 1;
        g[v].pop_back();
        return;
    }
    for (int i = 0; i < g[v].size(); i++) {
        int u = g[v][i];
        if (u == p) {
            g[v].erase(g[v].begin() + i);
        } else {
            dfs(u, v);
            leaves[v] += leaves[u];
        }
    }
}

void dyn(int v) {
    /* cout << "> " << v << " leaves " << leaves[v] << endl; */
    if (g[v].size() == 0) {
        z1[0][v][0] = 0;
        z1[0][v][1] = INF;
        z1[1][v][0] = INF;
        z1[1][v][1] = 0;
        return;
    }

    int cnt = 0;
    for (int i = g[v].size() - 1; i >= 0; --i) {
        int u = g[v][i];
        int nu = -1;
        if (i != g[v].size() - 1) {
            nu = g[v][i + 1];
        }
        /* cout << ": " << u << " " << nu << endl; */
        dyn(u);
        cnt += leaves[u];
        short one = 1;
        for (int j = 0; j <= cnt; j++) {
            for (short col = 0; col <= 1; ++col) {
                if (i == g[v].size() - 1) {
                    short x = z1[1 ^ col][u][j] + 1;
                    z2[col][u][j] = min(z1[col][u][j], x);
                } else {
                    short &val = z2[col][u][j];
                    val = INF;
                    for (int a = 0; a <= min(leaves[u], j); ++a) {
                        /* printf("z2(%d %d %d) = min z2(%d %d %d) + z1(0, %d, %d) + %d\n", col, u, j, col, nu, j - a, u, a, col); */
                        /* printf("> %d\n", z1[0][u][a]); */
                        if (j - a <= cnt - leaves[u]) {
                            short x = z2[col][nu][j - a] + z1[0][u][a] + (col);
                            val = min(val, x);
                            x = z2[col][nu][j - a] + z1[1][u][a] + (one^col);
                            val = min(val, x);
                        }
                    }
                }
                /* printf("z2(%d %d %d)=%d\n", col, u, j, z2[col][u][j]); */
            }
        }
    }
    /* cout << "v = " << v << endl; */
    for (int i = 0; i <= leaves[v]; ++i) {
        z1[0][v][i] = z2[0][g[v][0]][i];
        z1[1][v][i] = z2[1][g[v][0]][i];
        /* cout << "(" << z1[0][v][i] << " " << z1[1][v][i] << ") "; */
    }
    /* cout << endl; */
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);
    cin >> n;

    if (n == 2) {
        cout << 1 << endl;
        return 0;
    }

    forn (i, n - 1) {
        int from, to;
        cin >> from >> to;
        from--;
        to--;
        g[from].pb(to);
        g[to].pb(from);
    }

    int root = -1;

    forn (i, n) {
        if (g[i].size() != 1) {
            root = i;
            break;
        }
    }

    dfs(root);
    dyn(root);

    int ans1 = z1[0][root][leaves[root] / 2];
    int ans2 = z1[1][root][leaves[root] / 2];

    cout << min(ans1, ans2) << endl;
    return 0;
}


#include <bits/stdc++.h>
#define INF 2e9
#define pb push_back
#define mp make_pair
#define forn(i,n) for (int i = 0; i < n; i++)

using namespace std;

typedef long long ll;

const int N = 5123;
int n;
vector<int> g[N];

int z1[2][N][N];
int z2[2][N][N];
int leaves[N];

void dfs(int v, int p = -1) {
    if (g[v].size() == 1) {
        leaves[v] = 1;
        g[v].pop_back();
        return;
    }
    for (int i = 0; i < g[v].size(); i++) {
        int u = g[v][i];
        if (u == p) {
            g[v].erase(g[v].begin() + i);
        } else {
            dfs(u, v);
            leaves[v] += leaves[u];
        }
    }
}

void dyn(int v) {
    /* cout << "> " << v << " leaves " << leaves[v] << endl; */
    if (g[v].size() == 0) {
        z1[0][v][0] = 0;
        z1[0][v][1] = INF;
        z1[1][v][0] = INF;
        z1[1][v][1] = 0;
        return;
    }

    int cnt = 0;
    for (int i = g[v].size() - 1; i >= 0; --i) {
        int u = g[v][i];
        int nu = -1;
        if (i != g[v].size() - 1) {
            nu = g[v][i + 1];
        }
        /* cout << ": " << u << " " << nu << endl; */
        dyn(u);
        cnt += leaves[u];
        for (int j = 0; j <= cnt; j++) {
            for (int col = 0; col <= 1; ++col) {
                if (i == g[v].size() - 1) {
                    z2[col][u][j] = min(z1[col][u][j], z1[1 ^ col][u][j] + 1);
                } else {
                    int &val = z2[col][u][j];
                    val = INF;
                    for (int a = 0; a <= min(leaves[u], j); ++a) {
                        /* printf("z2(%d %d %d) = min z2(%d %d %d) + z1(0, %d, %d) + %d\n", col, u, j, col, nu, j - a, u, a, col); */
                        /* printf("> %d\n", z1[0][u][a]); */
                        if (j - a <= cnt - leaves[u]) {
                            val = min(val, z2[col][nu][j - a] + z1[0][u][a] + col);
                            val = min(val, z2[col][nu][j - a] + z1[1][u][a] + 1^col);
                        }
                    }
                }
                /* printf("z2(%d %d %d)=%d\n", col, u, j, z2[col][u][j]); */
            }
        }
    }
    /* cout << "v = " << v << endl; */
    for (int i = 0; i <= leaves[v]; ++i) {
        z1[0][v][i] = z2[0][g[v][0]][i];
        z1[1][v][i] = z2[1][g[v][0]][i];
        /* cout << "(" << z1[0][v][i] << " " << z1[1][v][i] << ") "; */
    }
    /* cout << endl; */
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);
    cin >> n;

    if (n == 2) {
        cout << 1 << endl;
        return 0;
    }

    forn (i, n - 1) {
        int from, to;
        cin >> from >> to;
        from--;
        to--;
        g[from].pb(to);
        g[to].pb(from);
    }

    int root = -1;

    forn (i, n) {
        if (g[i].size() != 1) {
            root = i;
            break;
        }
    }

    dfs(root);
    dyn(root);

    int ans1 = z1[0][root][leaves[root] / 2];
    int ans2 = z1[1][root][leaves[root] / 2];

    cout << min(ans1, ans2) << endl;
    return 0;
}


#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}
#define maxn 5005
#define inf 0x3f3f3f3f
int n,m,rt,res;
struct edge{
	int to,nxt;
}e[maxn<<1];
int tot,head[maxn];
inline void adde(int u,int v){
	e[++tot]=(edge){v,head[u]};
	head[u]=tot;
}

int dp[maxn][maxn][2],sz[maxn],g[2];
#define f(i,j,k) dp[i][j][k]
void dfs(int u,int pa)
{
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==pa)continue;
		dfs(v,u);sz[u]+=sz[v];
		if(sz[u]==sz[v]){
			For(j,0,sz[v]){
				f(u,j,0)=min(f(v,j,0),f(v,j,1)+1);
				f(u,j,1)=min(f(v,j,1),f(v,j,0)+1);
			}continue;
		}
		Rep(j,sz[u],0)
		{
			g[0]=g[1]=inf;
			For(k,0,min(sz[v],j)){
				g[0]=min(g[0],min(f(v,k,0),f(v,k,1)+1)+f(u,j-k,0));
				g[1]=min(g[1],min(f(v,k,1),f(v,k,0)+1)+f(u,j-k,1));
			}
			For(k,0,1)f(u,j,k)=g[k];
		}
	}
	if(!sz[u]){
		sz[u]=1;
		f(u,0,1)=f(u,1,0)=0;
		return;
	}
}
signed main()
{
	srand(19260817);srand(rand());srand(rand());
	memset(dp,63,sizeof dp);
	n=read();
	For(i,2,n){
		int u=read(),v=read();
		adde(u,v);adde(v,u);
	}
	rt=rand()%n+1;
	dfs(rt,0);
	cout<<min(f(rt,sz[rt]/2,0),f(rt,sz[rt]/2,1));
    return 0;
}


#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}
#define maxn 5005
#define inf 0x3f3f3f3f
int n,m,rt,res;
struct edge{
	int to,nxt;
}e[maxn<<1];
int tot,head[maxn];
inline void adde(int u,int v){
	e[++tot]=(edge){v,head[u]};
	head[u]=tot;
}
int d[maxn];
int dp[maxn][maxn][2],sz[maxn],g[2];
#define f(i,j,k) dp[i][j][k]
void dfs(int u,int pa)
{
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==pa)continue;
		dfs(v,u);sz[u]+=sz[v];
		if(sz[u]==sz[v]){
			For(j,0,sz[v]){
				f(u,j,0)=min(f(v,j,0),f(v,j,1)+1);
				f(u,j,1)=min(f(v,j,1),f(v,j,0)+1);
			}continue;
		}
		Rep(j,sz[u],0)
		{
			g[0]=g[1]=inf;
			For(k,0,min(sz[v],j)){
				g[0]=min(g[0],min(f(v,k,0),f(v,k,1)+1)+f(u,j-k,0));
				g[1]=min(g[1],min(f(v,k,1),f(v,k,0)+1)+f(u,j-k,1));
			}
			For(k,0,1)f(u,j,k)=g[k];
		}
	}
	if(!sz[u]){
		sz[u]=1;
		f(u,0,1)=f(u,1,0)=0;
		return;
	}
}
signed main()
{
//	srand(19260817);srand(rand());srand(rand());
	memset(dp,63,sizeof dp);
	n=read();
	if(n==2){
		puts("1");
		return 0;
	}
	For(i,2,n){
		int u=read(),v=read();
		adde(u,v);adde(v,u);
		d[u]++,d[v]++;
	}
	For(i,1,n)if(d[i]>1){rt=i;break;}
	dfs(rt,0);
	cout<<min(f(rt,sz[rt]/2,0),f(rt,sz[rt]/2,1));
    return 0;
}


#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}
#define maxn 5005
#define inf 0x3f3f3f3f
int n,m,rt,res;
struct edge{
	int to,nxt;
}e[maxn<<1];
int tot,head[maxn];
inline void adde(int u,int v){
	e[++tot]=(edge){v,head[u]};
	head[u]=tot;
}

int dp[maxn][maxn][2],sz[maxn],g[2];
#define f(i,j,k) dp[i][j][k]
void dfs(int u,int pa)
{
	memset(dp[u],63,sizeof dp[u]);
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==pa)continue;
		dfs(v,u);sz[u]+=sz[v];
		if(sz[u]==sz[v]){
			For(j,0,sz[v]){
				f(u,j,0)=min(f(v,j,0),f(v,j,1)+1);
				f(u,j,1)=min(f(v,j,1),f(v,j,0)+1);
			}continue;
		}
		Rep(j,sz[u],0)
		{
			g[0]=g[1]=inf;
			For(k,0,min(sz[v],j)){
				g[0]=min(g[0],min(f(v,k,0),f(v,k,1)+1)+f(u,j-k,0));
				g[1]=min(g[1],min(f(v,k,1),f(v,k,0)+1)+f(u,j-k,1));
			}
			For(k,0,1)f(u,j,k)=g[k];
		}
	}
	if(!sz[u]){
		sz[u]=1;
		f(u,0,0)=f(u,1,1)=0;
		return;
	}
}
signed main()
{
	n=read();
	For(i,2,n){
		int u=read(),v=read();
		adde(u,v);adde(v,u);
	}
	dfs(1,0);
	cout<<min(f(1,sz[1]>>1,0),f(1,sz[1]>>1,1));
    return 0;
}


#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}
#define maxn 5005
#define inf 0x3f3f3f3f
int n,m,rt,res;
struct edge{
	int to,nxt;
}e[maxn<<1];
int tot,head[maxn];
inline void adde(int u,int v){
	e[++tot]=(edge){v,head[u]};
	head[u]=tot;
}

int dp[maxn][maxn][2],sz[maxn],g[2];
#define f(i,j,k) dp[i][j][k]
void dfs(int u,int pa)
{
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==pa)continue;
		dfs(v,u);sz[u]+=sz[v];
		if(sz[u]==sz[v]){
			For(j,0,sz[v]){
				f(u,j,0)=min(f(v,j,0),f(v,j,1)+1);
				f(u,j,1)=min(f(v,j,1),f(v,j,0)+1);
			}continue;
		}
		Rep(j,sz[u],0)
		{
			g[0]=g[1]=inf;
			For(k,0,min(sz[v],j)){
				g[0]=min(g[0],min(f(v,k,0),f(v,k,1)+1)+f(u,j-k,0));
				g[1]=min(g[1],min(f(v,k,1),f(v,k,0)+1)+f(u,j-k,1));
			}
			For(k,0,1)f(u,j,k)=g[k];
		}
	}
	if(!sz[u]){
		sz[u]=1;
		f(u,0,1)=f(u,1,0)=0;
		return;
	}
}
signed main()
{
	memset(dp,63,sizeof dp);
	n=read();
	For(i,2,n){
		int u=read(),v=read();
		adde(u,v);adde(v,u);
	}
	dfs(1,0);
	cout<<min(f(1,sz[1]/2,0),f(1,sz[1]/2,1));
    return 0;
}


// Copyright (c) Markus Hasenöhrl
//

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <string>
#include <map>
#include <set>
#include <tr1/unordered_map>
#include <tr1/unordered_set>
#include <vector>
#include <math.h>
#include <algorithm>
#include <assert.h>
#include <limits.h>
#include <float.h>
#include <stack>
#include <queue>
#include <bitset>
#include <list>
#include <iostream>
#include <sstream>
using namespace std;
using namespace tr1;
typedef long long lint;
typedef long double real;

vector<int> adj[5009];
int degree[5009];

struct NODE
{
	NODE() {p = left = right = -1; leafes = 0; isLeafe = false; bl = br = false;}
	int p;
	int left, right;
	bool bl, br;
	int leafes;
	bool isLeafe;
}nodes[10009];

int _next = 0;

pair<int, int> init(int n, int from, int p)
{
	vector<int> v, to;
	for(int i = 0; i < adj[n].size(); i++)
	{
		if(adj[n][i] == from) continue;
		v.push_back(_next);
		to.push_back(adj[n][i]);
		_next++;
	}

	if(v.size() == 0)
	{
		int nn = _next;
		_next++;
		nodes[nn].isLeafe = true;
		nodes[nn].leafes = 1;

		return make_pair(nn, nodes[nn].leafes);
	}

	for(int i = 0; i < v.size(); i++)
	{
		pair<int, int> x = init(to[i], n, v[i]);
		nodes[v[i]].left = x.first;
		nodes[v[i]].leafes = x.second;
		if(i != v.size() - 1)
			nodes[v[i]].right = v[i + 1];
		nodes[v[i]].br = true;
	}
	nodes[v[0]].br = false;

	for(int i = v.size() - 2; i >= 0; i--)
		nodes[v[i]].leafes += nodes[v[i + 1]].leafes;

	return make_pair(v[0], nodes[v[0]].leafes);
}

int dp[10100][3000][2];
int recurse(int n, int t1, int last)
{
	if(t1 > nodes[n].leafes)
		return 10000000;
	if(n == -1 && t1 != 0)
		return 10000000;
	if(n == -1) return 0;

	if(dp[n][t1][last] != -1)
		return dp[n][t1][last];

	if(nodes[n].isLeafe)
	{
		if(t1 > 1) return 10000000;
		if(t1 == 1 && last == 0) return 0;
		if(t1 == 1 && last == 1) return 1;
		if(t1 == 0 && last == 0) return 1;
		if(t1 == 0 && last == 1) return 0;
		assert(0);
	}

	int mini = 100000000;
	int maxL = nodes[nodes[n].left].leafes;
	int maxR = nodes[n].right == -1 ? 0 : nodes[nodes[n].right].leafes;
	for(int i = max(0, t1-maxR); i <= t1 && i <= nodes[nodes[n].left].leafes; i++)
	{
		int r1 = recurse(nodes[n].left, i, last) + recurse(nodes[n].right, t1 - i, last);
		int r2 = 10000000;
		if(!nodes[n].br)
			r2 = recurse(nodes[n].left, i, !last) + recurse(nodes[n].right, t1 - i, !last) + 1;
		mini = min(mini, r1);
		mini = min(mini, r2);
	}

	return dp[n][t1][last] = mini;
}

int main()
{
	int n;
	cin >> n;
	for(int i = 1; i <= n - 1; i++)
	{
		int a, b;
		cin >> a >> b;
		adj[a].push_back(b);
		adj[b].push_back(a);
		degree[a]++;
		degree[b]++;
	}

	int leafes = 0, start = -1;
	for(int i = 1; i <= n; i++)
	{
		if(degree[i] == 1)
			leafes++;
		else
			start = i;
	}

	//cout << start << endl;
	pair<int, int> p = init(start, -1, -1);

	memset(dp, 0xff, sizeof dp);

	/*for(int i = 0; i < _next; i++)
	{
		cout << i << " " << nodes[i].left << " " << nodes[i].right << " " << nodes[i].isLeafe << " " << nodes[i].leafes << endl;
	}
	cout << leafes << endl;*/

	//return 0;

	int m1 = recurse(0, leafes / 2, 0);
	int m2 = recurse(0, leafes / 2, 1);

	//cout << m1 << " " << m2 << endl;

	cout << min(m1, m2) << endl;

	return 0;
}


// Copyright (c) Markus Hasenöhrl
//

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <string>
#include <map>
#include <set>
#include <tr1/unordered_map>
#include <tr1/unordered_set>
#include <vector>
#include <math.h>
#include <algorithm>
#include <assert.h>
#include <limits.h>
#include <float.h>
#include <stack>
#include <queue>
#include <bitset>
#include <list>
#include <iostream>
#include <sstream>
using namespace std;
using namespace tr1;
typedef long long lint;
typedef long double real;

vector<int> adj[5009];
int degree[5009];

struct NODE
{
	NODE() {p = left = right = -1; leafes = 0; isLeafe = false; bl = br = false;}
	int p;
	int left, right;
	bool bl, br;
	int leafes;
	bool isLeafe;
}nodes[10009];

int _next = 0;

pair<int, int> init(int n, int from, int p)
{
	vector<int> v, to;
	for(int i = 0; i < adj[n].size(); i++)
	{
		if(adj[n][i] == from) continue;
		v.push_back(_next);
		to.push_back(adj[n][i]);
		_next++;
	}

	if(v.size() == 0)
	{
		int nn = _next;
		_next++;
		nodes[nn].isLeafe = true;
		nodes[nn].leafes = 1;

		return make_pair(nn, nodes[nn].leafes);
	}

	for(int i = 0; i < v.size(); i++)
	{
		pair<int, int> x = init(to[i], n, v[i]);
		nodes[v[i]].left = x.first;
		nodes[v[i]].leafes = x.second;
		if(i != v.size() - 1)
			nodes[v[i]].right = v[i + 1];
		nodes[v[i]].br = true;
	}
	nodes[v[0]].br = false;

	for(int i = v.size() - 2; i >= 0; i--)
		nodes[v[i]].leafes += nodes[v[i + 1]].leafes;

	return make_pair(v[0], nodes[v[0]].leafes);
}

int dp[10100][3000][2];
int recurse(int n, int t1, int last)
{
	if(t1 > nodes[n].leafes)
		return 10000000;
	if(n == -1 && t1 != 0)
		return 10000000;
	if(n == -1) return 0;

	if(dp[n][t1][last] != -1)
		return dp[n][t1][last];

	if(nodes[n].isLeafe)
	{
		if(t1 > 1) return 10000000;
		if(t1 == 1 && last == 0) return 0;
		if(t1 == 1 && last == 1) return 1;
		if(t1 == 0 && last == 0) return 1;
		if(t1 == 0 && last == 1) return 0;
		assert(0);
	}

	int mini = 100000000;
	for(int i = 0; i <= t1 && i <= nodes[nodes[n].left].leafes; i++)
	{
		int r1 = recurse(nodes[n].left, i, last) + recurse(nodes[n].right, t1 - i, last);
		int r2 = 10000000;
		if(!nodes[n].br)
			r2 = recurse(nodes[n].left, i, !last) + recurse(nodes[n].right, t1 - i, !last) + 1;
		mini = min(mini, r1);
		mini = min(mini, r2);
	}

	return dp[n][t1][last] = mini;
}

int main()
{
	int n;
	cin >> n;
	for(int i = 1; i <= n - 1; i++)
	{
		int a, b;
		cin >> a >> b;
		adj[a].push_back(b);
		adj[b].push_back(a);
		degree[a]++;
		degree[b]++;
	}

	int leafes = 0, start = -1;
	for(int i = 1; i <= n; i++)
	{
		if(degree[i] == 1)
			leafes++;
		else
			start = i;
	}

	//cout << start << endl;
	pair<int, int> p = init(start, -1, -1);

	memset(dp, 0xff, sizeof dp);

	/*for(int i = 0; i < _next; i++)
	{
		cout << i << " " << nodes[i].left << " " << nodes[i].right << " " << nodes[i].isLeafe << " " << nodes[i].leafes << endl;
	}
	cout << leafes << endl;*/

	//return 0;

	int m1 = recurse(0, leafes / 2, 0);
	int m2 = recurse(0, leafes / 2, 1);

	//cout << m1 << " " << m2 << endl;

	cout << min(m1, m2) << endl;

	return 0;
}


// Copyright (c) Markus Hasenöhrl
//

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <string>
#include <map>
#include <set>
#include <tr1/unordered_map>
#include <tr1/unordered_set>
#include <vector>
#include <math.h>
#include <algorithm>
#include <assert.h>
#include <limits.h>
#include <float.h>
#include <stack>
#include <queue>
#include <bitset>
#include <list>
#include <iostream>
#include <sstream>
using namespace std;
using namespace tr1;
typedef long long lint;
typedef long double real;

vector<int> adj[5009];
int degree[5009];

struct NODE
{
	NODE() {p = left = right = -1; leafes = 0; isLeafe = false; bl = br = false;}
	int p;
	int left, right;
	bool bl, br;
	int leafes;
	bool isLeafe;
}nodes[10009];

int _next = 0;

pair<int, int> init(int n, int from, int p)
{
	vector<int> v, to;
	for(int i = 0; i < adj[n].size(); i++)
	{
		if(adj[n][i] == from) continue;
		v.push_back(_next);
		to.push_back(adj[n][i]);
		_next++;
	}

	if(v.size() == 0)
	{
		int nn = _next;
		_next++;
		nodes[nn].isLeafe = true;
		nodes[nn].leafes = 1;

		return make_pair(nn, nodes[nn].leafes);
	}

	for(int i = 0; i < v.size(); i++)
	{
		pair<int, int> x = init(to[i], n, v[i]);
		nodes[v[i]].left = x.first;
		nodes[v[i]].leafes = x.second;
		if(i != v.size() - 1)
			nodes[v[i]].right = v[i + 1];
		nodes[v[i]].br = true;
	}
	nodes[v[0]].br = false;

	for(int i = v.size() - 2; i >= 0; i--)
		nodes[v[i]].leafes += nodes[v[i + 1]].leafes;

	return make_pair(v[0], nodes[v[0]].leafes);
}

int dp[10100][3000][2];
int recurse(int n, int t1, int last)
{
	if(t1 > nodes[n].leafes)
		return 10000000;
	if(n == -1 && t1 != 0)
		return 10000000;
	if(n == -1) return 0;

	if(dp[n][t1][last] != -1)
		return dp[n][t1][last];

	if(nodes[n].isLeafe)
	{
		if(t1 > 1) return 10000000;
		if(t1 == 1 && last == 0) return 0;
		if(t1 == 1 && last == 1) return 1;
		if(t1 == 0 && last == 0) return 1;
		if(t1 == 0 && last == 1) return 0;
		assert(0);
	}

	int mini = 100000000;
	int maxL = nodes[nodes[n].left].leafes;
	int maxR = nodes[n].right == -1 ? 0 : nodes[nodes[n].right].leafes;
	for(int i = 0/*max(0, t1-maxR)*/; i <= t1 /*&& i <= nodes[nodes[n].left].leafes*/; i++)
	{
		int r1 = recurse(nodes[n].left, i, last) + recurse(nodes[n].right, t1 - i, last);
		int r2 = 10000000;
		if(!nodes[n].br)
			r2 = recurse(nodes[n].left, i, !last) + recurse(nodes[n].right, t1 - i, !last) + 1;
		mini = min(mini, r1);
		mini = min(mini, r2);
	}

	return dp[n][t1][last] = mini;
}

int main()
{
	int n;
	cin >> n;
	for(int i = 1; i <= n - 1; i++)
	{
		int a, b;
		cin >> a >> b;
		adj[a].push_back(b);
		adj[b].push_back(a);
		degree[a]++;
		degree[b]++;
	}

	int leafes = 0, start = -1;
	for(int i = 1; i <= n; i++)
	{
		if(degree[i] == 1)
			leafes++;
		else
			start = i;
	}

	//cout << start << endl;
	pair<int, int> p = init(start, -1, -1);

	memset(dp, 0xff, sizeof dp);

	/*for(int i = 0; i < _next; i++)
	{
		cout << i << " " << nodes[i].left << " " << nodes[i].right << " " << nodes[i].isLeafe << " " << nodes[i].leafes << endl;
	}
	cout << leafes << endl;*/

	//return 0;

	int m1 = recurse(0, leafes / 2, 0);
	int m2 = recurse(0, leafes / 2, 1);

	//cout << m1 << " " << m2 << endl;

	cout << min(m1, m2) << endl;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<int> g[N], tree[N];
int vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

map<pair<pair<int, int>, pair<int, int>>, int> dp;
const int inf = 10000;

// a = 0, b = 1
int f(int i, int j, int a, int prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) return prev == 1;
		return inf;
	}
	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}
	auto arg = mk(mk(i, j), mk(a, prev));
	if (dp.count(arg)) return dp[arg];

	int ans = 0;

	int r1 = f(tree[i][j], 0, min(a, lvs[tree[i][j]]), 0) + f(i, j + 1, a - min(a, lvs[tree[i][j]]), prev) + (prev == 1);
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[arg] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	if (n <= 2) {
		cout << 0 << endl;
		return 0;
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<int> g[N], tree[N];
int vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

map<pair<pair<int, int>, pair<int, int>>, int> dp;
const int inf = 10000;

// a = 0, b = 1
int f(int i, int j, int a, int prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) return prev == 1;
		return inf;
	}

	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}
	auto arg = mk(mk(i, j), mk(a, prev));
	if (dp.count(arg)) return dp[arg];

	int ans = 0;

	int r1 = inf;
	if(a > 0) r1 = min(f(tree[i][j], 0, min(a, lvs[tree[i][j]]), 0) + prev == 1, f(tree[i][j], 0, min(a, lvs[tree[i][j]]), 1) + prev == 0)+ f(i, j + 1, a - min(a, lvs[tree[i][j]]), prev) + (prev == 1);
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[arg] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<int> g[N], tree[N];
int vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

map<pair<pair<int, int>, pair<int, int>>, int> dp;
const int inf = 10000;

// a = 0, b = 1
int f(int i, int j, int a, int prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) return 0;
		return inf;
	}
	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}
	auto arg = mk(mk(i, j), mk(a, prev));
	if (dp.count(arg)) return dp[arg];

	int ans = 0;

	int r1 = f(tree[i][j], 0, min(a, lvs[tree[i][j]]), 0) + f(i, j + 1, a - min(a, lvs[tree[i][j]]), prev) + (prev == 1);
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[arg] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	if (n <= 2) {
		cout << 0 << endl;
		return 0;
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<short> g[N], tree[N];
short vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

vector<vector<vector<short>>> dp[5000];
const int inf = 10000;

// a = 0, b = 1
short f(short i, short j, short a, short prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) {
			if (prev == 0) return 0;
		}
		return inf;
	}
	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}

	if (dp[i][j][a][prev] != -1) return dp[i][j][a][prev];

	short ans = 0;

	int r1 = inf;
	for (int aa = 1; aa <= min(a, lvs[tree[i][j]]); aa++){
		r1 = min(r1, min(f(tree[i][j], 0, aa, 0) + (prev == 1), f(tree[i][j], 0, aa, 1) + (prev == 0)) + f(i, j + 1, a - aa, prev));
	}
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[i][j][a][prev] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	if (n == 2) {
		cout << 0 << endl;
		return 0;
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	for (int i = 0; i < n; i++){
		dp[i].resize(tree[i].size(), vector<vector<short>>(lvs[i] + 1, vector<short>(2, -1)));
	}

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<short> g[N], tree[N];
short vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

vector<vector<vector<short>>> dp[5000];
const int inf = 10000;

// a = 0, b = 1
int f(int i, int j, int a, int prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) {
			if (prev == 0) return 0;
		}
		return inf;
	}
	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}

	if (dp[i][j][a][prev] != -1) return dp[i][j][a][prev];

	int ans = 0;

	int r1 = inf;
	for (int aa = 1; aa <= min(a, lvs[tree[i][j]]); aa++){
		r1 = min(r1, min(f(tree[i][j], 0, aa, 0) + (prev == 1), f(tree[i][j], 0, aa, 1) + (prev == 0)) + f(i, j + 1, a - aa, prev));
	}
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[i][j][a][prev] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	if (n == 2) {
		cout << 0 << endl;
		return 0;
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	for (int i = 0; i < n; i++){
		dp[i].resize(tree[i].size(), vector<vector<short>>(lvs[i] + 1, vector<short>(2, -1)));
	}

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<int> g[N], tree[N];
int vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

vector<vector<vector<int>>> dp[5000];
const int inf = 10000;

// a = 0, b = 1
int f(int i, int j, int a, int prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) {
			if (prev == 0) return 0;
		}
		return inf;
	}
	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}

	if (dp[i][j][a][prev] != -1) return dp[i][j][a][prev];

	int ans = 0;

	int r1 = inf;
	for (int aa = 1; aa <= min(a, lvs[tree[i][j]]); aa++){
		r1 = min(r1, min(f(tree[i][j], 0, aa, 0) + (prev == 1), f(tree[i][j], 0, aa, 1) + (prev == 0)) + f(i, j + 1, a - aa, prev));
	}
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[i][j][a][prev] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	if (n == 2) {
		cout << 0 << endl;
		return 0;
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	for (int i = 0; i < n; i++){
		dp[i].resize(tree[i].size(), vector<vector<int>>(lvs[i], vector<int>(2, -1)));

	}

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<int> g[N], tree[N];
int vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

map<pair<pair<int, int>, pair<int, int>>, int> dp;
const int inf = 10000;

// a = 0, b = 1
int f(int i, int j, int a, int prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) {
			if (prev == 0) return 0;
		}
		return inf;
	}

	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}
	auto arg = mk(mk(i, j), mk(a, prev));
	if (dp.count(arg)) return dp[arg];

	int ans = 0;

	int r1 = inf;
	if(a > 0) r1 = min(f(tree[i][j], 0, min(a, lvs[tree[i][j]]), 0) + (prev == 1), f(tree[i][j], 0, min(a, lvs[tree[i][j]]), 1) + (prev == 0)) + f(i, j + 1, a - min(a, lvs[tree[i][j]]), prev);
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[arg] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<int> g[N], tree[N];
int vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

map<pair<pair<int, int>, pair<int, int>>, int> dp;
const int inf = 10000;

// a = 0, b = 1
int f(int i, int j, int a, int prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) {
			if (prev == 0) return 0;
		}
		return inf;
	}
	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}
	auto arg = mk(mk(i, j), mk(a, prev));
	if (dp.count(arg)) return dp[arg];

	int ans = 0;

	int r1 = inf;
	for (int aa = 1; aa <= min(a, lvs[tree[i][j]]); aa++){
		r1 = min(r1, min(f(tree[i][j], 0, aa, 0) + (prev == 1), f(tree[i][j], 0, aa, 1) + (prev == 0)) + f(i, j + 1, a - aa, prev));
	}
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[arg] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	if (n == 2) {
		cout << 0 << endl;
		return 0;
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<short> g[N], tree[N];
short vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

vector<vector<short>> dp[5000][2];
const int inf = 10000;

// a = 0, b = 1
short f(short i, short j, short a, short prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) {
			if (prev == 0) return 0;
		}
		return inf;
	}
	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}

	if (dp[i][prev][j][a] != -1) return dp[i][prev][j][a];

	short ans = 0;

	int r1 = inf;
	for (int aa = 1; aa <= min(a, lvs[tree[i][j]]); aa++){
		r1 = min(r1, min(f(tree[i][j], 0, aa, 0) + (prev == 1), f(tree[i][j], 0, aa, 1) + (prev == 0)) + f(i, j + 1, a - aa, prev));
	}
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[i][prev][j][a] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	if (n == 2) {
		cout << 0 << endl;
		return 0;
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	for (int i = 0; i < n; i++){
		for (int j = 0; j < 2; j++){
			dp[i][j].resize(tree[i].size(), vector<short>(lvs[i] + 1, -1));
		}
	}

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<int> g[N], tree[N];
int vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

map<pair<pair<int, int>, pair<int, int>>, int> dp;
const int inf = 10000;

// a = 0, b = 1
int f(int i, int j, int a, int prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) {
			if (prev == 0) return 0;
		}
		return inf;
	}

	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}
	auto arg = mk(mk(i, j), mk(a, prev));
	if (dp.count(arg)) return dp[arg];

	int ans = 0;

	int r1 = inf;
	if(a > 0) r1 = min(f(tree[i][j], 0, min(a, lvs[tree[i][j]]), 0) + (prev == 1), f(tree[i][j], 0, min(a, lvs[tree[i][j]]), 1) + (prev == 0)) + f(i, j + 1, a - min(a, lvs[tree[i][j]]), prev);
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[arg] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	if (n == 2) {
		cout << 0 << endl;
		return 0;
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <fstream>
#include <algorithm>
#include <string>
#include <cmath>
#include <bitset>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <ctime>
#include <cstring>
#include <list>
//#include <forward_list>
#include <iomanip>
#include <cassert>
#include <functional>
using namespace std;
#define ll long long
#define Long long long
#define mk make_pair
//----------------------------
//
//
//#define cin fin
//#ifdef cin
//ifstream fin("in.txt");
//#endif

const int N = 5000;

vector<int> g[N], tree[N];
int vis[N], lvs[N];

void dfs(int s){
	vis[s] = 1;
	for (int i = 0; i < g[s].size(); i++){
		if (!vis[g[s][i]]){
			tree[s].push_back(g[s][i]);
			dfs(g[s][i]);
		}
	}
}

int h(int s){
	if (tree[s].size() == 0) return lvs[s] = 1;
	int ans = 0;
	for (int i = 0; i < tree[s].size(); i++){
		ans += h(tree[s][i]);
	}
	return lvs[s] = ans;
}

vector<vector<vector<int>>> dp[5000];
const int inf = 10000;

// a = 0, b = 1
int f(int i, int j, int a, int prev){
	if (a < 0) return inf;
	if (tree[i].size() == 0) {
		if (a == 1) {
			if (prev == 0) return 0;
		}
		return inf;
	}
	if (j == tree[i].size()){
		if (a == 0) return 0;
		else return inf;
	}

	if (dp[i][j][a][prev] != -1) return dp[i][j][a][prev];

	int ans = 0;

	int r1 = inf;
	for (int aa = 1; aa <= min(a, lvs[tree[i][j]]); aa++){
		r1 = min(r1, min(f(tree[i][j], 0, aa, 0) + (prev == 1), f(tree[i][j], 0, aa, 1) + (prev == 0)) + f(i, j + 1, a - aa, prev));
	}
	int r2 = f(i, j + 1, a, prev) + (prev == 0);
	ans = min(r1, r2);
	return dp[i][j][a][prev] = ans;
}

int main(){
	int n;
	cin >> n;
	int u, v;
	for (int i = 0; i < n - 1; i++){
		cin >> u >> v;
		u--; v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	if (n == 2) {
		cout << 0 << endl;
		return 0;
	}

	int root;
	for (int i = 0; i < n; i++) if (g[i].size() > 1) root = i;
	dfs(root);
	h(root);

	for (int i = 0; i < n; i++){
		dp[i].resize(tree[i].size(), vector<vector<int>>(lvs[i] + 1, vector<int>(2, -1)));

	}

	int ans = min(f(root, 0, lvs[root] / 2, 0), f(root, 0, lvs[root] / 2, 1));
	cout << ans << endl;

#undef cin
	int _______________;
	cin >> _______________;

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (int i=s;i<=t;i++)
#define pi acos(-1)
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<double, double> PDD;
typedef pair<PII, PII> PPP;
typedef pair<PII, int> PPI;
#define repp(i,s,t) for (int i=s;i>=t;i--)
template<class T> T sqr(T x) {return x*x;}
#define debug(x) cerr<<#x"="<<(x)<<endl;
#define pb(x) push_back(x);
#define ori(x) x-'a'
const int maxn = 5010;
int f2[maxn][maxn][2];
int vis2[maxn][maxn][2];
int n, m, x, y, k, p;
vector<int> g[maxn];
int leaf[maxn];
int bro[maxn];
int first_son[maxn];
const int inf = 10000;
void dfs(int k, int last = -1)
{
    int flag = 1;
    int lastt = -1;
    for (int i = 0 ; i < g[k].size(); i++)
    if (g[k][i] != last)
    {
        flag = 0;
        dfs(g[k][i], k);
        if (lastt != -1) bro[lastt] = g[k][i];
        else first_son[k] = g[k][i];
        leaf[k] += leaf[g[k][i]];
        lastt = g[k][i];
    }
    leaf[k] += flag;
}
int dp(int k, int cnt, int col);
int dp2(int k, int cnt, int col)
{
    if (k == 0)
    {
        if (cnt) return inf;
        return 0;
    }
    if (vis2[k][cnt][col]) return f2[k][cnt][col];
    vis2[k][cnt][col] = 1;
    f2[k][cnt][col] = inf;
    int nex_son = bro[k];
    rep(cur_cnt, 0, cnt)
    rep(cur_col, 0, 1)
        f2[k][cnt][col] = min(f2[k][cnt][col],
            dp(k, cur_cnt, cur_col) + dp2(nex_son, cnt - cur_cnt, col)
             + (cur_col != col));
    return f2[k][cnt][col];
}
int dp(int k, int cnt, int col)
{
    if (cnt > leaf[k]) return inf;
    if (g[k].size() == 1)
    {
        if (cnt + col == 1) return 0;
        else return inf;
    }
    return dp2(first_son[k], cnt, col);
}
int main()
{
    scanf("%d",&n);
    for (int i = 0 ; i < n - 1; i ++)
    {
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    int root = 1;
    rep(i,1,n) if (g[i].size() > 1)
    {
        root = i;
        break;
    }
    dfs(root);
    int st = leaf[root];
    cout << min(dp(root,st/2,0), dp(root,st/2,1)) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (int i=s;i<=t;i++)
#define pi acos(-1)
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<double, double> PDD;
typedef pair<PII, PII> PPP;
typedef pair<PII, int> PPI;
#define repp(i,s,t) for (int i=s;i>=t;i--)
template<class T> T sqr(T x) {return x*x;}
#define debug(x) cerr<<#x"="<<(x)<<endl;
#define pb(x) push_back(x);
#define ori(x) x-'a'
const int maxn = 5010;
int f2[maxn][maxn][2];
int vis2[maxn][maxn][2];
int n, m, x, y, k, p;
vector<int> g[maxn];
int leaf[maxn];
int bro[maxn];
int first_son[maxn];
const int inf = 10000;
void dfs(int k, int last = -1)
{
    int flag = 1;
    int lastt = -1;
    for (int i = 0 ; i < g[k].size(); i++)
    if (g[k][i] != last)
    {
        flag = 0;
        dfs(g[k][i], k);
        if (lastt != -1) bro[lastt] = g[k][i];
        else first_son[k] = g[k][i];
        leaf[k] += leaf[g[k][i]];
        lastt = g[k][i];
    }
    leaf[k] += flag;
}
int dp(int k, int cnt, int col);
int dp2(int k, int cnt, int col)
{
    if (k == 0)
    {
        if (cnt) return inf;
        return 0;
    }
    if (vis2[k][cnt][col]) return f2[k][cnt][col];
    vis2[k][cnt][col] = 1;
    f2[k][cnt][col] = inf;
    int nex_son = bro[k];
    rep(cur_cnt, 0, min(cnt, leaf[k]))
    rep(cur_col, 0, 1)
        f2[k][cnt][col] = min(f2[k][cnt][col],
            dp(k, cur_cnt, cur_col) + dp2(nex_son, cnt - cur_cnt, col)
             + (cur_col != col));
    return f2[k][cnt][col];
}
inline int dp(int k, int cnt, int col)
{
    if (cnt > leaf[k]) return inf;
    if (g[k].size() == 1)
    {
        if (cnt + col == 1) return 0;
        else return inf;
    }
    return dp2(first_son[k], cnt, col);
}
int main()
{
    scanf("%d",&n);
    for (int i = 0 ; i < n - 1; i ++)
    {
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    int root = 1;
    rep(i,1,n) if (g[i].size() > 1)
    {
        root = i;
        break;
    }
    dfs(root);
    int st = leaf[root];
    cout << min(dp(root,st/2,0), dp(root,st/2,1)) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (int i=s;i<=t;i++)
#define pi acos(-1)
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<double, double> PDD;
typedef pair<PII, PII> PPP;
typedef pair<PII, int> PPI;
#define repp(i,s,t) for (int i=s;i>=t;i--)
template<class T> T sqr(T x) {return x*x;}
#define debug(x) cerr<<#x"="<<(x)<<endl;
#define pb(x) push_back(x);
#define ori(x) x-'a'
const int maxn = 5010;
int f2[maxn][maxn][2];
int vis2[maxn][maxn][2];
int n, m, x, y, k, p;
vector<int> g[maxn];
int leaf[maxn];
int bro[maxn];
int first_son[maxn];
const int inf = 10000;
void dfs(int k, int last = -1)
{
    int flag = 1;
    int lastt = -1;
    for (int i = 0 ; i < g[k].size(); i++)
    if (g[k][i] != last)
    {
        flag = 0;
        dfs(g[k][i], k);
        if (lastt != -1) bro[lastt] = g[k][i];
        else first_son[k] = g[k][i];
        leaf[k] += leaf[g[k][i]];
        lastt = g[k][i];
    }
    leaf[k] += flag;
}
int dp(int k, int cnt, int col);
int dp2(int k, int cnt, int col)
{
    if (k == 0)
    {
        if (cnt) return inf;
        return 0;
    }
    if (vis2[k][cnt][col]) return f2[k][cnt][col];
    vis2[k][cnt][col] = 1;
    f2[k][cnt][col] = inf;
    int nex_son = bro[k];
    rep(cur_cnt, 0, cnt)
    rep(cur_col, 0, 1)
        f2[k][cnt][col] = min(f2[k][cnt][col],
            dp(k, cur_cnt, cur_col) + dp2(nex_son, cnt - cur_cnt, col)
             + (cur_col != col));
    return f2[k][cnt][col];
}
inline int dp(int k, int cnt, int col)
{
    if (cnt > leaf[k]) return inf;
    if (g[k].size() == 1)
    {
        if (cnt + col == 1) return 0;
        else return inf;
    }
    return dp2(first_son[k], cnt, col);
}
int main()
{
    scanf("%d",&n);
    for (int i = 0 ; i < n - 1; i ++)
    {
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    int root = 1;
    rep(i,1,n) if (g[i].size() > 1)
    {
        root = i;
        break;
    }
    dfs(root);
    int st = leaf[root];
    cout << min(dp(root,st/2,0), dp(root,st/2,1)) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (int i=s;i<=t;i++)
#define pi acos(-1)
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<double, double> PDD;
typedef pair<PII, PII> PPP;
typedef pair<PII, int> PPI;
#define repp(i,s,t) for (int i=s;i>=t;i--)
template<class T> T sqr(T x) {return x*x;}
#define debug(x) cerr<<#x"="<<(x)<<endl;
#define pb(x) push_back(x);
#define ori(x) x-'a'
const int maxn = 6001;
int f1[maxn][maxn][2], f2[maxn][maxn][2];
int z[maxn][maxn][2];
int vis1[maxn][maxn][2], vis2[maxn][maxn][2];
int n, m, x, y, k, p;
vector<int> g[maxn];
int leaf[maxn];
int bro[maxn];
int first_son[maxn];
const int inf = 10000;
void dfs(int k, int last = -1)
{
	int flag = 1;
	int lastt = -1;
	for (int i = 0 ; i < g[k].size(); i++)
	if (g[k][i] != last)
	{
		flag = 0;
		dfs(g[k][i], k);
		if (lastt != -1) bro[lastt] = g[k][i];
		else first_son[k] = g[k][i];
		leaf[k] += leaf[g[k][i]];
		lastt = g[k][i];
	}
	leaf[k] += flag;
}
int dp(int k, int cnt, int col);
int dp2(int k, int cnt, int col)
{
	if (k == 0)
	{
		if (cnt) return inf;
		return 0;
	}
	if (vis2[k][cnt][col]) return f2[k][cnt][col];
	vis2[k][cnt][col] = 1;
	f2[k][cnt][col] = inf;
	int nex_son = bro[k];
	rep(cur_cnt, 0, cnt)
	rep(cur_col, 0, 1)
		f2[k][cnt][col] = min(f2[k][cnt][col],
			dp(k, cur_cnt, cur_col) + dp2(nex_son, cnt - cur_cnt, col)
			 + (cur_col != col));
	return f2[k][cnt][col];
}
int dp(int k, int cnt, int col)
{
	if (cnt > leaf[k]) return inf;
	if (g[k].size() == 1)
	{
		if (cnt + col == 1) return 0;
		else return inf;
	}
	if (vis1[k][cnt][col]) return f1[k][cnt][col];
	vis1[k][cnt][col] = 1;
	f1[k][cnt][col] = dp2(first_son[k], cnt, col);
	return f1[k][cnt][col];
}
int main()
{
	scanf("%d",&n);
	for (int i = 0 ; i < n - 1; i ++)
	{
		scanf("%d%d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	int root = 1;
	rep(i,1,n) if (g[i].size() > 1)
	{
		root = i;
		break;
	}
	dfs(root);
	int st = leaf[root];
	dp(root, st/2 , 0);
	dp(root, st/2 , 1);
	cout << min(f1[root][st/2][0], f1[root][st/2][1]) << endl;
}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (int i=s;i<=t;i++)
#define pi acos(-1)
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<double, double> PDD;
typedef pair<PII, PII> PPP;
typedef pair<PII, int> PPI;
#define repp(i,s,t) for (int i=s;i>=t;i--)
template<class T> T sqr(T x) {return x*x;}
#define debug(x) cerr<<#x"="<<(x)<<endl;
#define pb(x) push_back(x);
#define ori(x) x-'a'
const int maxn = 5010;
int f1[maxn][maxn][2], f2[maxn][maxn][2];
int z[maxn][maxn][2];
int vis1[maxn][maxn][2], vis2[maxn][maxn][2];
int n, m, x, y, k, p;
vector<int> g[maxn];
int leaf[maxn];
int bro[maxn];
int first_son[maxn];
const int inf = 10000;
void dfs(int k, int last = -1)
{
    int flag = 1;
    int lastt = -1;
    for (int i = 0 ; i < g[k].size(); i++)
    if (g[k][i] != last)
    {
        flag = 0;
        dfs(g[k][i], k);
        if (lastt != -1) bro[lastt] = g[k][i];
        else first_son[k] = g[k][i];
        leaf[k] += leaf[g[k][i]];
        lastt = g[k][i];
    }
    leaf[k] += flag;
}
int dp(int k, int cnt, int col);
int dp2(int k, int cnt, int col)
{
    if (k == 0)
    {
        if (cnt) return inf;
        return 0;
    }
    if (vis2[k][cnt][col]) return f2[k][cnt][col];
    vis2[k][cnt][col] = 1;
    f2[k][cnt][col] = inf;
    int nex_son = bro[k];
    rep(cur_cnt, 0, cnt)
    rep(cur_col, 0, 1)
        f2[k][cnt][col] = min(f2[k][cnt][col],
            dp(k, cur_cnt, cur_col) + dp2(nex_son, cnt - cur_cnt, col)
             + (cur_col != col));
    return f2[k][cnt][col];
}
int dp(int k, int cnt, int col)
{
    if (cnt > leaf[k]) return inf;
    if (g[k].size() == 1)
    {
        if (cnt + col == 1) return 0;
        else return inf;
    }
    if (vis1[k][cnt][col]) return f1[k][cnt][col];
    vis1[k][cnt][col] = 1;
    f1[k][cnt][col] = dp2(first_son[k], cnt, col);
    return f1[k][cnt][col];
}
int main()
{
    scanf("%d",&n);
    for (int i = 0 ; i < n - 1; i ++)
    {
        scanf("%d%d",&x,&y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    int root = 1;
    rep(i,1,n) if (g[i].size() > 1)
    {
        root = i;
        break;
    }
    dfs(root);
    int st = leaf[root];
    dp(root, st/2 , 0);
    dp(root, st/2 , 1);
    cout << min(f1[root][st/2][0], f1[root][st/2][1]) << endl;
}


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <iomanip>
#include <string>
#include <ctime>
#include <list>
#include <bitset>
#include <conio.h>
typedef unsigned char byte;
#define pb push_back
#define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
#define local freopen("in.txt","r",stdin)
#define pi acos(-1)

using namespace std;
const int maxn = 5e3 + 15;
struct Edge{int v , nxt;};
int sz[maxn],head[maxn],n,tot=0,root,dp[maxn][maxn][2],errorcode;
Edge e[maxn*2];

void add(int u,int v)
{
	e[tot].v = v , e[tot].nxt= head[u],head[u] = tot++ , sz[u]++;
}

void initiation()
{
	memset(sz,0,sizeof(sz));memset(dp,0x3f,sizeof(dp));memset(head,-1,sizeof(head));
	errorcode = dp[0][0][0];
	scanf("%d",&n);
	for(int i = 1 ; i < n ; ++ i)
	{
		int u , v;
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
}

inline void updata(int & x ,int v)
{
	x = min(x , v );
}

int dfs(int u ,int fa)
{
	int res = 0;
	if(sz[u] == 1)  res = 1 ,  dp[u][1][0] = dp[u][0][1] = 0;
	else dp[u][0][1] = dp[u][0][0] = 0;
	for(int i = head[u] ; ~i ; i = e[i].nxt)
	{
		int v = e[i].v;
		if(v == fa) continue;
		int t = dfs(v,u);
		for(int j = res ; j >= 0 ; -- j)
		{
			for(int k = t ; k >= 1 ; -- k)
			{
			    updata( dp[u][j+k][0] , dp[u][j][0] + dp[v][k][1] + 1);
		        updata( dp[u][j+k][0] , dp[u][j][0] + dp[v][k][0]);
		     	updata( dp[u][j+k][1] , dp[u][j][1] + dp[v][k][1]);
			    updata( dp[u][j+k][1] , dp[u][j][1] + dp[v][k][0] + 1);
			}
			int s1 = min(dp[v][0][1] + 1 , dp[v][0][0]);
			dp[u][j][0] = s1 > (1<<20) ? errorcode : s1 + dp[u][j][0];
			s1 = min(dp[v][0][1],dp[v][0][0]+1);
			dp[u][j][1] = s1 > (1<<20) ? errorcode : s1 + dp[u][j][1];
		}
		res += t;
	}
	return res;
}

void solve()
{
	int res = 0;
	for(int i = 1 ; i <= n ; ++ i) if(sz[i] != 1) {root = i ; break;}
	for(int i = 1 ; i <= n ; ++ i) if(sz[i] == 1) res ++ ;
	dfs(root,0);
	printf("%d\n",min(dp[root][res/2][0],dp[root][res/2][1]));
}

int main(int argc,char *argv[])
{
	initiation();
	if(n == 2) printf("1\n");
	else solve();
	return 0;
}


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <iomanip>
#include <string>
#include <ctime>
#include <list>
#include <bitset>
#include <conio.h>
typedef unsigned char byte;
#define pb push_back
#define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
#define local freopen("in.txt","r",stdin)
#define pi acos(-1)

using namespace std;
const int maxn = 5e3 + 15;
struct Edge{int v , nxt;};
int sz[maxn],head[maxn],n,tot=0,root,dp[maxn][maxn][2],errorcode;
Edge e[maxn*2];

void add(int u,int v)
{
	e[tot].v = v , e[tot].nxt= head[u],head[u] = tot++ , sz[u]++;
}

void initiation()
{
	memset(sz,0,sizeof(sz));memset(dp,0x3f,sizeof(dp));memset(head,-1,sizeof(head));
	errorcode = dp[0][0][0];
	scanf("%d",&n);
	for(int i = 1 ; i < n ; ++ i)
	{
		int u , v;
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
}

inline void updata(int & x ,int v)
{
	x = min(x , v );
}

int dfs(int u ,int fa)
{
	int res = 0;
	if(sz[u] == 1)  res = 1 ,  dp[u][1][0] = dp[u][0][1] = 0;
	else dp[u][0][1] = dp[u][0][0] = 0;
	for(int i = head[u] ; ~i ; i = e[i].nxt)
	{
		int v = e[i].v;
		if(v == fa) continue;
		int t = dfs(v,u);
		for(int j = res ; j >= 0 ; -- j)
		{
			for(int k = t ; k >= 1 ; -- k)
			{
			    updata( dp[u][j+k][0] , dp[u][j][0] + dp[v][k][1] + 1);
		        updata( dp[u][j+k][0] , dp[u][j][0] + dp[v][k][0]);
		     	updata( dp[u][j+k][1] , dp[u][j][1] + dp[v][k][1]);
			    updata( dp[u][j+k][1] , dp[u][j][1] + dp[v][k][0] + 1);
			}
			int s1 = min(dp[v][0][1] + 1 , dp[v][0][0]);
			dp[u][j][0] = s1 > (1<<20) ? errorcode : s1 + dp[u][j][0];
			s1 = min(dp[v][0][1],dp[v][0][0]+1);
			dp[u][j][1] = s1 > (1<<20) ? errorcode : s1 + dp[u][j][1];
		}
		res += t;
	}
	return res;
}

void solve()
{
	int res = 0;
	for(int i = 1 ; i <= n ; ++ i) if(sz[i] != 1) {root = i ; break;}
	for(int i = 1 ; i <= n ; ++ i) if(sz[i] == 1) res ++ ;
	dfs(root,0);
	printf("%d\n",min(dp[root][res/2][0],dp[root][res/2][1]));
}

int main(int argc,char *argv[])
{
	local;
	initiation();
	if(n == 2) printf("1\n");
	else solve();
	return 0;
}


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <queue>
#include <iomanip>
#include <string>
#include <ctime>
#include <list>
#include <bitset>
#include <conio.h>
typedef unsigned char byte;
#define pb push_back
#define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0)
#define local freopen("in.txt","r",stdin)
#define pi acos(-1)

using namespace std;
const int maxn = 5e3 + 15;
struct Edge{int v , nxt;};
int sz[maxn],head[maxn],n,tot=0,root,dp[maxn][maxn][2],errorcode;
Edge e[maxn*2];

void add(int u,int v)
{
	e[tot].v = v , e[tot].nxt= head[u],head[u] = tot++ , sz[u]++;
}

void initiation()
{
	memset(sz,0,sizeof(sz));memset(dp,0x1f,sizeof(dp));memset(head,-1,sizeof(head));
	errorcode = dp[0][0][0];
	scanf("%d",&n);
	for(int i = 1 ; i < n ; ++ i)
	{
		int u , v;
		scanf("%d%d",&u,&v);
		add(u,v);add(v,u);
	}
}

inline void updata(int & x ,int v)
{
	x = min(x , v );
}

int dfs(int u ,int fa)
{
	int res = 0;
	if(sz[u] == 1)  res = 1 ,  dp[u][1][0] = dp[u][0][1] = 0;
	else dp[u][0][1] = dp[u][0][0] = 0;
	for(int i = head[u] ; ~i ; i = e[i].nxt)
	{
		int v = e[i].v;
		if(v == fa) continue;
		int t = dfs(v,u);
		for(int j = res ; j >= 0 ; -- j)
		{
			for(int k = 0 ; k <= t ; ++ k)
			{
			    updata( dp[u][j+k][0] , dp[u][j][0] + dp[v][k][1] + 1);
		        updata( dp[u][j+k][0] , dp[u][j][0] + dp[v][k][0]);
		     	updata( dp[u][j+k][1] , dp[u][j][1] + dp[v][k][1]);
			    updata( dp[u][j+k][1] , dp[u][j][1] + dp[v][k][0] + 1);
			}
			//dp[u][j][0] = dp[u][j][1] = errorcode;
		}
		res += t;
	}
	return res;
}

void solve()
{
	int res = 0;
	for(int i = 1 ; i <= n ; ++ i) if(sz[i] != 1) {root = i ; break;}
	for(int i = 1 ; i <= n ; ++ i) if(sz[i] == 1) res ++ ;
	dfs(root,0);
   // cout << dp[root][res/2][0] << " " << dp[root][res/2][1] << endl;
	printf("%d\n",dp[root][res/2][1]);
}

int main(int argc,char *argv[])
{
	initiation();
	if(n == 2) printf("1\n");
	else solve();
	return 0;
}


#include<bits/stdc++.h>
#define ts cout<<"ok"<<endl
#define ll long long
#define hh puts("")
#define pc putchar
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
//char buf[1<<21],*p1=buf,*p2=buf;
using namespace std;
const int N=5005;
int n,head[N],cnt,f[N][N][2],sz[N],deg[N],g[N][2],rt;
struct Edge{
	int v,nx;
}e[N<<1];
inline int read(){
    int ret=0,ff=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') ff=-1;ch=getchar();}
    while(isdigit(ch)){ret=ret*10+(ch^48);ch=getchar();}
    return ret*ff;
}
void write(int x){if(x<0){x=-x,pc('-');}if(x>9) write(x/10);pc(x%10+48);}
void writeln(int x){write(x),hh;}
void writesp(int x){write(x),pc(' ');}
void add(int x,int y){
	e[++cnt].v=y;
	e[cnt].nx=head[x];
	head[x]=cnt;
}
//f[u][i][0/1]:u为0/1,u子树i个叶子为0的最小ans
void dfs(int u,int fa){
	if(deg[u]>1) f[u][0][0]=f[u][0][1]=0;
	else sz[u]=1,f[u][0][1]=f[u][1][0]=0;
	for(int t=head[u];t;t=e[t].nx){
		int v=e[t].v;
		if(v==fa) continue;
		dfs(v,u);
		memset(g,0x3f,sizeof(g));
		for(int i=0;i<=sz[u];i++){
			for(int j=0;j<=sz[v];j++){
				 g[i+j][0]=min(g[i+j][0],min(f[u][i][0]+f[v][j][0],f[u][i][0]+f[v][j][1]+1));
				 g[i+j][1]=min(g[i+j][1],min(f[u][i][1]+f[v][j][0]+1,f[u][i][1]+f[v][j][1]));
			}
		}
		sz[u]+=sz[v];
		for(int i=0;i<=sz[u];i++) f[u][i][0]=g[i][0],f[u][i][1]=g[i][1];
	}
}
signed main(){
	n=read();
	if(n==2){
		write(1);
		return 0;
	}
	for(int i=1;i<n;i++){
		int x=read(),y=read();
		add(x,y),add(y,x);
		deg[x]++,deg[y]++;
	}
	for(int i=1;i<=n;i++)
		if(deg[i]>1)
			rt=i;
	memset(f,0x3f,sizeof(f));
	dfs(rt,0);
	write(min(f[rt][sz[rt]/2][0],f[rt][sz[rt]/2][1]));
    return 0;
}


#include<bits/stdc++.h>
#define ts cout<<"ok"<<endl
#define ll long long
#define hh puts("")
#define pc putchar
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
//char buf[1<<21],*p1=buf,*p2=buf;
using namespace std;
const int N=5005;
int n,head[N],cnt,f[N][N][2],sz[N],g[N][2];
struct Edge{
	int v,nx;
}e[N<<1];
inline int read(){
    int ret=0,ff=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') ff=-1;ch=getchar();}
    while(isdigit(ch)){ret=ret*10+(ch^48);ch=getchar();}
    return ret*ff;
}
void write(int x){if(x<0){x=-x,pc('-');}if(x>9) write(x/10);pc(x%10+48);}
void writeln(int x){write(x),hh;}
void writesp(int x){write(x),pc(' ');}
void add(int x,int y){
	e[++cnt].v=y;
	e[cnt].nx=head[x];
	head[x]=cnt;
}
//f[u][i][0/1]:u为0/1,u子树i个叶子为0的最小ans
void dfs(int u,int fa){
	f[u][0][0]=f[u][0][1]=0;
	int son=0;
	for(int t=head[u];t;t=e[t].nx){
		int v=e[t].v;
		if(v==fa) continue;
		dfs(v,u);
		son++;
		memset(g,0x3f,sizeof(g));
		for(int i=0;i<=sz[u];i++){
			for(int j=0;j<=sz[v];j++){
				 g[i+j][0]=min(g[i+j][0],min(f[u][i][0]+f[v][j][0],f[u][i][0]+f[v][j][1]+1));
				 g[i+j][1]=min(g[i+j][1],min(f[u][i][1]+f[v][j][0]+1,f[u][i][1]+f[v][j][1]));
			}
		}
		sz[u]+=sz[v];
		for(int i=0;i<=sz[u];i++) f[u][i][0]=g[i][0],f[u][i][1]=g[i][1];
	}
	if(!son) sz[u]=1,f[u][0][1]=f[u][1][0]=0,f[u][0][0]=0x3f3f3f3f;
}
signed main(){
	n=read();
	for(int i=1;i<n;i++){
		int x=read(),y=read();
		add(x,y),add(y,x);
	}
	memset(f,0x3f,sizeof(f));
	dfs(1,0);
	write(min(f[1][sz[1]/2][0],f[1][sz[1]/2][1]));
    return 0;
}


#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <iostream>
#include <cmath>
#include <sstream>
#include <map>
#include <set>
#include <numeric>
#include <memory.h>
#include <cstdio>
#include <assert.h>

using namespace std;

#define pb push_back
#define INF 1011111111
#define FOR(i, a, b) for (int _n(b), i(a); i < _n; i++)
#define rep(i, n) FOR(i, 0, n)
#define CL(a, v) memset((a), (v), sizeof(a))
#define mp make_pair
#define X first
#define Y second
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> pii;

/*** TEMPLATE CODE ENDS HERE */

const int N = 5005;
VI g[N];
int leafs[N];

void dfs(int x, int p) {
  leafs[x] = g[x].size() == 1;
  for (int y : g[x]) {
    if (y != p) {
      dfs(y, x);
      leafs[x] += leafs[y];
    }
  }
}

int dp[N];
int ans;
int H;

void dfs2(int x, int p, int num) {
  for (int y : g[x]) {
    if (y != p) {
      dfs2(y, x, num + leafs[x] - leafs[y]);
    }
  }
  if (g[x].size() == 1) return;
  VI a = {num};
  for (int y : g[x]) {
    if (y != p) {
      a.pb(leafs[y]);
    }
  }
  //  int n = accumulate(all(a), 0);
  //  assert(n % 2 == 0);
  //  n /= 2;
  fill_n(dp, H + 1, INF);
  dp[0] = 0;
  for (int v : a) {
    for (int i = H; i >= v; --i) {
      dp[i] = min(dp[i], dp[i - v] + 1);
    }
  }
  ans = min(ans, dp[H]);
}

int main() {
#ifdef LOCAL_HOST
  freopen("input.txt", "r", stdin);
// freopen("output.txt","w",stdout);
#endif

  ios_base::sync_with_stdio(false);

  int n;
  cin >> n;
  rep(i, n - 1) {
    int x, y;
    cin >> x >> y;
    --x, --y;
    g[x].pb(y);
    g[y].pb(x);
  }

  int root = -1;
  rep(i, n) if (g[i].size() > 1) {
    root = i;
    break;
  }
  H = 0;
  rep(i, n) H += g[i].size() == 1;
  H /= 2;

  dfs(root, -1);
  ans = INF;
  dfs2(root, -1, 0);
  cout << ans << endl;

#ifdef LOCAL_HOST
  printf("TIME: %.3lf\n", double(clock()) / CLOCKS_PER_SEC);
#endif

  return 0;
}


#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <iostream>
#include <cmath>
#include <sstream>
#include <map>
#include <set>
#include <numeric>
#include <memory.h>
#include <cstdio>
#include <assert.h>

using namespace std;

#define pb push_back
#define INF 1011111111
#define FOR(i, a, b) for (int _n(b), i(a); i < _n; i++)
#define rep(i, n) FOR(i, 0, n)
#define CL(a, v) memset((a), (v), sizeof(a))
#define mp make_pair
#define X first
#define Y second
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> pii;

/*** TEMPLATE CODE ENDS HERE */

const int N = 5005;
VI g[N];
int leafs[N];

void dfs(int x, int p) {
  leafs[x] = g[x].size() == 1;
  for (int y : g[x]) {
    if (y != p) {
      dfs(y, x);
      leafs[x] += leafs[y];
    }
  }
}

int dp[N];
int ans;

void dfs2(int x, int p, int num) {
  for (int y : g[x]) {
    if (y != p) {
      dfs2(y, x, num + leafs[x] - leafs[y]);
    }
  }
  VI a = {num};
  for (int y : g[x]) {
    if (y != p) {
      a.pb(leafs[y]);
    }
  }
  if (g[x].size() == 1) return;
  int n = accumulate(all(a), 0);
  assert(n % 2 == 0);
  n /= 2;
  fill_n(dp, n + 1, INF);
  dp[0] = 0;
  for (int v : a) {
    for (int i = n; i >= v; --i) {
      dp[i] = min(dp[i], dp[i - v] + 1);
    }
  }
  ans = min(ans, dp[n]);
}

int main() {
#ifdef LOCAL_HOST
  freopen("input.txt", "r", stdin);
// freopen("output.txt","w",stdout);
#endif

  ios_base::sync_with_stdio(false);

  int n;
  cin >> n;
  rep(i, n - 1) {
    int x, y;
    cin >> x >> y;
    --x, --y;
    g[x].pb(y);
    g[y].pb(x);
  }

  dfs(0, -1);
  ans = INF;
  dfs2(0, -1, 0);
  cout << ans << endl;

#ifdef LOCAL_HOST
  printf("TIME: %.3lf\n", double(clock()) / CLOCKS_PER_SEC);
#endif

  return 0;
}


#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <iostream>
#include <cmath>
#include <sstream>
#include <map>
#include <set>
#include <numeric>
#include <memory.h>
#include <cstdio>
#include <assert.h>

using namespace std;

#define pb push_back
#define INF 1011111111
#define FOR(i, a, b) for (int _n(b), i(a); i < _n; i++)
#define rep(i, n) FOR(i, 0, n)
#define CL(a, v) memset((a), (v), sizeof(a))
#define mp make_pair
#define X first
#define Y second
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> pii;

/*** TEMPLATE CODE ENDS HERE */

const int N = 5005;
VI g[N];
int leafs[N];

void dfs(int x, int p) {
  leafs[x] = g[x].size() == 1;
  for (int y : g[x]) {
    if (y != p) {
      dfs(y, x);
      leafs[x] += leafs[y];
    }
  }
}

int dp[N];
int ans;

void dfs2(int x, int p, int num) {
  for (int y : g[x]) {
    if (y != p) {
      dfs2(y, x, num + leafs[x] - leafs[y]);
    }
  }
  if (g[x].size() == 1) return;
  VI a = {num};
  for (int y : g[x]) {
    if (y != p) {
      a.pb(leafs[y]);
    }
  }
  int n = accumulate(all(a), 0);
  assert(n % 2 == 0);
  n /= 2;
  fill_n(dp, n + 1, INF);
  dp[0] = 0;
  for (int v : a) {
    for (int i = n; i >= v; --i) {
      dp[i] = min(dp[i], dp[i - v] + 1);
    }
  }
  ans = min(ans, dp[n]);
}

int main() {
#ifdef LOCAL_HOST
  freopen("input.txt", "r", stdin);
// freopen("output.txt","w",stdout);
#endif

  ios_base::sync_with_stdio(false);

  int n;
  cin >> n;
  rep(i, n - 1) {
    int x, y;
    cin >> x >> y;
    --x, --y;
    g[x].pb(y);
    g[y].pb(x);
  }

  int root = -1;
  rep(i, n) if (g[i].size() > 1) {
    root = i;
    break;
  }

  dfs(root, -1);
  ans = INF;
  dfs2(root, -1, 0);
  cout << ans << endl;

#ifdef LOCAL_HOST
  printf("TIME: %.3lf\n", double(clock()) / CLOCKS_PER_SEC);
#endif

  return 0;
}


#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <iostream>
#include <cmath>
#include <sstream>
#include <map>
#include <set>
#include <numeric>
#include <memory.h>
#include <cstdio>
#include <assert.h>

using namespace std;

#define pb push_back
#define INF 1011111111
#define FOR(i, a, b) for (int _n(b), i(a); i < _n; i++)
#define rep(i, n) FOR(i, 0, n)
#define CL(a, v) memset((a), (v), sizeof(a))
#define mp make_pair
#define X first
#define Y second
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> pii;

/*** TEMPLATE CODE ENDS HERE */

const int N = 5005;
VI g[N];
int leafs[N];

void dfs(int x, int p) {
  leafs[x] = g[x].size() == 1;
  for (int y : g[x]) {
    if (y != p) {
      dfs(y, x);
      leafs[x] += leafs[y];
    }
  }
}

int dp[N];
int ans;
int H;

void dfs2(int x, int p, int num) {
  for (int y : g[x]) {
    if (y != p) {
      dfs2(y, x, num + leafs[x] - leafs[y]);
    }
  }
  if (g[x].size() == 1) return;
  VI a = {num};
  for (int y : g[x]) {
    if (y != p) {
      a.pb(leafs[y]);
    }
  }
  //  int n = accumulate(all(a), 0);
  //  assert(n % 2 == 0);
  //  n /= 2;
  fill_n(dp, H + 1, INF);
  dp[0] = 0;
  for (int v : a) {
    for (int i = H; i >= v; --i) {
      dp[i] = min(dp[i], dp[i - v] + 1);
    }
  }
  ans = min(ans, dp[H]);
}

int main() {
#ifdef LOCAL_HOST
  freopen("input.txt", "r", stdin);
// freopen("output.txt","w",stdout);
#endif

  ios_base::sync_with_stdio(false);

  int n;
  cin >> n;
  rep(i, n - 1) {
    int x, y;
    cin >> x >> y;
    --x, --y;
    g[x].pb(y);
    g[y].pb(x);
  }

  int root = -1;
  rep(i, n) if (g[i].size() > 1) {
    root = i;
    break;
  }

  dfs(root, -1);
  ans = INF;
  H = n / 2;
  dfs2(root, -1, 0);
  cout << ans << endl;

#ifdef LOCAL_HOST
  printf("TIME: %.3lf\n", double(clock()) / CLOCKS_PER_SEC);
#endif

  return 0;
}


#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <iostream>
#include <cmath>
#include <sstream>
#include <map>
#include <set>
#include <numeric>
#include <memory.h>
#include <cstdio>
#include <assert.h>

using namespace std;

#define pb push_back
#define INF 1011111111
#define FOR(i, a, b) for (int _n(b), i(a); i < _n; i++)
#define rep(i, n) FOR(i, 0, n)
#define CL(a, v) memset((a), (v), sizeof(a))
#define mp make_pair
#define X first
#define Y second
#define all(c) (c).begin(), (c).end()
#define SORT(c) sort(all(c))

typedef long long ll;
typedef vector<int> VI;
typedef pair<int, int> pii;

/*** TEMPLATE CODE ENDS HERE */

const int N = 5005;
VI g[N];
int leafs[N];

void dfs(int x, int p) {
  leafs[x] = g[x].size() == 1;
  for (int y : g[x]) {
    if (y != p) {
      dfs(y, x);
      leafs[x] += leafs[y];
    }
  }
}

// int dp[N];
// int ans;
//
// void dfs2(int x, int p, int num) {
//  for (int y : g[x]) {
//    if (y != p) {
//      dfs2(y, x, num + leafs[x] - leafs[y]);
//    }
//  }
//  if (g[x].size() == 1) return;
//  VI a = {num};
//  for (int y : g[x]) {
//    if (y != p) {
//      a.pb(leafs[y]);
//    }
//  }
//  int n = accumulate(all(a), 0);
//  assert(n % 2 == 0);
//  n /= 2;
//  fill_n(dp, n + 1, INF);
//  dp[0] = 0;
//  for (int v : a) {
//    for (int i = n; i >= v; --i) {
//      dp[i] = min(dp[i], dp[i - v] + 1);
//    }
//  }
//  ans = min(ans, dp[n]);
//}

int dp[N][N][2];

inline int min(int x, int y, int z) { return min(x, min(y, z)); }

void solve(int at, int from) {
  rep(i, leafs[at] + 1) rep(j, 2) dp[at][i][j] = N;
  if (g[at].size() == 1) {
    dp[at][1][1] = 0;
    dp[at][0][0] = 0;
    dp[at][0][1] = N;
    dp[at][1][0] = N;
    return;
  }
  int sc = 0;
  VI cur0(sc + 1, 0);
  VI cur1(sc + 1, 0);
  for (auto to : g[at])
    if (to != from) {
      solve(to, at);
      sc += leafs[to];

      VI nxt0(sc + 1, INF);
      VI nxt1(sc + 1, INF);

      rep(c, sc - leafs[to] + 1) rep(r, leafs[to] + 1) {
        nxt0[c + r] = min(nxt0[c + r], cur0[c] + dp[to][r][0],
                          cur0[c] + dp[to][r][1] + 1);
        nxt1[c + r] = min(nxt1[c + r], cur1[c] + dp[to][r][1],
                          cur1[c] + dp[to][r][0] + 1);
      }

      cur0 = nxt0;
      cur1 = nxt1;
    }

  assert((int)cur0.size() == leafs[at] + 1);

  rep(i, leafs[at] + 1) {
    dp[at][i][0] = cur0[i];
    dp[at][i][1] = cur1[i];
  }
}

int main() {
#ifdef LOCAL_HOST
  freopen("input.txt", "r", stdin);
// freopen("output.txt","w",stdout);
#endif

  ios_base::sync_with_stdio(false);

  int n;
  cin >> n;
  rep(i, n - 1) {
    int x, y;
    cin >> x >> y;
    --x, --y;
    g[x].pb(y);
    g[y].pb(x);
  }

  if (n == 2) {
    cout << 1 << endl;
    return 0;
  }

  int root = 0;
  while (root < n && g[root].size() == 1) ++root;

  dfs(root, -1);

  //  ans = INF;
  //  dfs2(0, -1, 0);
  //  cout << ans << endl;

  solve(root, -1);
  cout << min(dp[root][leafs[root] / 2][0], dp[root][leafs[root] / 2][1])
       << endl;

#ifdef LOCAL_HOST
  printf("TIME: %.3lf\n", double(clock()) / CLOCKS_PER_SEC);
#endif

  return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define sz(a) (int)a.size()

typedef long long ll;

const int N = (int)1e5 + 4;
const int M = 5001;
const int inf = (int)1e9 + 7;

vector<int> g[N];
int h[N];

bool ls(int a, int b) {
    return h[a] > h[b];
}

void go(int v, int p) {
    if (sz(g[v]) == 1) {
        h[v] = 1;
        return;
    }
    for (int i = 0; i < sz(g[v]); ++i) {
        int to = g[v][i];
        if (to != p) {
            go(to, v);
            h[v] += h[to];
        }
    }
}

int dfs(int v, int p, int k) {
    if (sz(g[v]) == 1) {
        return k;
    }
    int ans = 0, s = 0;
    for (int i = 0; i < sz(g[v]) && s < k; ++i) {
        int to = g[v][i];
        if (to == p) {
            continue;
        }
        s += h[to];
        if (s > k) {
            s -= h[to];
            ans += dfs(to, v, k - s);
        } else {
            ++ans;
        }
    }
    return ans;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int n;
    scanf("%d", &n);
    if (n == 2) {
        printf("1");
        return 0;
    }
    for (int i = 0; i < n - 1; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    int p = 0;
    for (int i = 0; i < n; ++i) {
        if (sz(g[i]) == 1) {
            ++p;
        }
    }
    int ans = inf;
    for (int i = 0; i < n; ++i) {
        if (sz(g[i]) > 1) {
            memset(h, 0, sizeof h);
            go(i, -1);
            for (int j = 0; j < n; ++j) {
                sort(g[j].begin(), g[j].end(), ls);
            }
            ans = min(ans, dfs(i, -1, p / 2));
        }
    }
    printf("%d", ans);
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define sz(a) (int)a.size()

typedef long long ll;

const int N = (int)1e5 + 4;
const int M = 5001;
const int inf = (int)1e9 + 7;

vector<int> g[M];
int dp[2][M][M][2];
int h[M];

void dfs(int v, int p) {
    if (sz(g[v]) == 1) {
        h[v]++;
        dp[0][v][1][0] = 0;
        dp[0][v][0][1] = 0;
        return;
    }
    for (int i = 0; i < sz(g[v]); ++i) {
        if (p == g[v][i]) {
            swap(g[v][i], g[v][sz(g[v]) - 1]);
            break;
        }
    }
    for (int i = 0; i < sz(g[v]) - (p != -1); ++i) {
        dfs(g[v][i], v);
        h[v] += h[g[v][i]];
    }
    for (int i = 0; i <= h[v]; ++i) {
        for (int w = 0; w < 2; ++w) {
            for (int x = sz(g[v]) - 1 - (p != -1); x >= 0; --x) {
                int to = g[v][x];
                for (int f = 0; f < 2; ++f) {
                    for (int k = 0; k <= min(i, h[to]); ++k) {
                        if (x == sz(g[v]) - 1 - (p != -1)) {
                            dp[1][to][i][w] = min(dp[1][to][i][w], dp[0][to][i][f] + (f != w));
                        } else {
                            int s = g[v][x + 1];
                            dp[1][to][i][w] = min(dp[1][to][i][w], dp[1][s][i - k][w] + dp[0][to][k][f] + (f != w));
                        }
                    }
                }
                if (x == 0) {
                    dp[0][v][i][w] = dp[1][to][i][w];
                }
            }
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int n;
    scanf("%d", &n);
    if (n == 2) {
        printf("1");
        return 0;
    }
    for (int i = 0; i < n - 1; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    int p = 0, k = 0;
    for (int i = 0; i < n; ++i) {
        if (sz(g[i]) > 1) {
            p = i;
        } else {
            ++k;
        }
    }
    for (int i = 0; i < 2; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                for (int t = 0; t < 2; ++t) {
                    dp[i][j][k][t] = inf;
                }
            }
        }
    }
    dfs(p, -1);
    printf("%d", min(dp[0][p][k / 2][0], dp[0][p][k / 2][1]));
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define sz(a) (int)a.size()

typedef long long ll;

const int N = (int)1e5 + 4;
const int M = 5001;
const int inf = (int)1e9 + 7;

vector<int> g[M];
int dp[2][M][M][2];
int h[M];

void dfs(int v, int p) {
    if (sz(g[v]) == 1) {
        h[v]++;
        dp[0][v][1][0] = 0;
        dp[0][v][0][1] = 0;
        return;
    }
    for (int i = 0; i < sz(g[v]); ++i) {
        if (p == g[v][i]) {
            swap(g[v][i], g[v][sz(g[v]) - 1]);
            break;
        }
    }
    for (int i = 0; i < sz(g[v]) - (p != -1); ++i) {
        dfs(g[v][i], v);
        h[v] += h[g[v][i]];
    }
    for (int i = 0; i < h[v]; ++i) {
        for (int w = 0; w < 2; ++w) {
            for (int x = sz(g[v]) - 1 - (p != -1); x >= 0; --x) {
                int to = g[v][x];
                for (int f = 0; f < 2; ++f) {
                    for (int k = 0; k <= min(i, h[to]); ++k) {
                        if (x == sz(g[v]) - 1 - (p != -1)) {
                            dp[1][to][i][w] = min(dp[1][to][i][w], dp[0][to][i][f] + (f != w));
                        } else {
                            int s = g[v][x + 1];
                            dp[1][to][i][w] = min(dp[1][to][i][w], dp[1][s][i - k][w] + dp[0][to][k][f] + (f != w));
                        }
                    }
                }
                if (x == 0) {
                    dp[0][v][i][w] = dp[1][to][i][w];
                }
            }
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int n;
    scanf("%d", &n);
    if (n == 2) {
        printf("1");
        return 0;
    }
    for (int i = 0; i < n - 1; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    int p = 0, k = 0;
    for (int i = 0; i < n; ++i) {
        if (sz(g[i]) > 1) {
            p = i;
        } else {
            ++k;
        }
    }
    for (int i = 0; i < 2; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                for (int t = 0; t < 2; ++t) {
                    dp[i][j][k][t] = inf;
                }
            }
        }
    }
    dfs(p, -1);
    printf("%d", min(dp[0][p][k / 2][0], dp[0][p][k / 2][1]));
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define sz(a) (int)a.size()

typedef long long ll;

const int N = (int)1e5 + 4;
const int M = 5001;
const int inf = (int)1e9 + 7;

vector<int> g[N];
int h[N];

bool ls(int a, int b) {
    return h[a] > h[b];
}

void go(int v, int p) {
    if (sz(g[v]) == 1) {
        h[v] = 1;
    }
    for (int i = 0; i < sz(g[v]); ++i) {
        int to = g[v][i];
        if (to != p) {
            go(to, v);
            h[v] += h[to];
        }
    }
}

int dfs(int v, int p, int k) {
    if (sz(g[v]) == 1) {
        return k;
    }
    int ans = 0, s = 0;
    for (int i = 0; i < sz(g[v]) && s < k; ++i) {
        int to = g[v][i];
        if (to == p) {
            continue;
        }
        s += h[to];
        if (s > k) {
            s -= h[to];
            ans += dfs(to, v, k - s);
        } else {
            ++ans;
        }
    }
    return ans;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int n;
    scanf("%d", &n);
    if (n == 2) {
        printf("1");
        return 0;
    }
    for (int i = 0; i < n - 1; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    int p = 0;
    for (int i = 0; i < n; ++i) {
        if (sz(g[i]) == 1) {
            ++p;
        }
    }
    int ans = inf;
    for (int i = 0; i < n; ++i) {
        if (sz(g[i]) > 1) {
            go(i, -1);
            for (int j = 0; j < n; ++j) {
                sort(g[j].begin(), g[j].end(), ls);
            }
            ans = min(ans, dfs(i, -1, p / 2));
        }
    }
    printf("%d", ans);
    return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define f first
#define s second
#define mp make_pair
#define sz(a) int((a).size())
#define fname "."

typedef long long ll;
typedef unsigned long long ull;

const int MAX_N = 5123;
const double eps = 1e-6;
const int inf = (int)1e9 + 123;

using namespace std;

int n;
vector < int > g[MAX_N];
int d[2][MAX_N][MAX_N];
int sz[MAX_N];

void dfs(int v, int pr = -1) {
	sz[v] = 0;
	int son = sz(g[v]);
	if (pr != -1)
		son--;
	if (!son) {
		sz[v] = 1;
		return;
	}
	for (auto to : g[v]) {
		if (to != pr) {
			dfs(to, v);
			sz[v] += sz[to];
		}
	}
}

int D(bool tp, int v, int cnt, int pr = -1) {
    int son = sz(g[v]);
    if (pr != -1)
    	son--;
	if (!son && ((!tp && cnt != 0) || (tp && cnt == 0)))
		return d[tp][v][cnt] = inf;
    if (cnt > sz[v])
    	return d[tp][v][cnt] = inf;
	if (!son)
		return d[tp][v][cnt] = 0;
	if (d[tp][v][cnt] != -1)
		return d[tp][v][cnt];
	int step = 0, id = 0;
//	if (v == 1)
//		cout << "im " << tp << endl;
	int pref[2][MAX_N];
	for (auto to : g[v]) {
	    if (to == pr)
	    	continue;
		for (int i = 0; i <= sz[v]; i++)
			pref[id][i] = inf;
		step++;
		if (step == 1) {
			for (int i = 0; i <= sz[to]; i++)
				for (int k = 0; k < 2; k++) {
//				    cout << "when " << to << " is " << k << " and " << v << " is " << tp << " with " << i << " is " << D(k, to, i, v) + (k != tp) << endl;
					pref[id][i] = min(pref[id][i], D(k, to, i, v) + (k != tp));
				}
		}
		else
			for (int i = 0; i <= sz[v]; i++)
				for (int j = 0; j <= min(i, sz[to]); j++) {
					for (int k = 0; k < 2; k++) {
//						if (to == 4) {
//							cout << id << " IIIDD\n";
//						    cout << "when " << to << " is " << k << " and " << v << " is " << tp << endl;
//						    cout << "when CNT " << to << " is " << j << " and " << v << " is " << i << endl;
//						    cout << "PPPPPP " << (id ^ 1) << ' ' << i - j << " isss " << pref[(id ^ 1)][i - j] << endl;
//							int f = pref[(id ^ 1)][i - j], s = D(k, to, j, v) + (k != tp);
//						    cout << D(k,to,j,v) << ' ' << D(k,to,j,v) << endl;
//						 	cout << "Isss " << f << " pref and D " << s << " sum " << f + s << endl;
//						 }
						pref[id][i] = min(pref[id][i], pref[id ^ 1][i - j] + D(k, to, j, v) + (k != tp));
					}
				}
//		if (v == 1) {
//			cout << "for " << to << endl;
//			for (int i = 0; i <= sz[v]; i++)
//				cout << id << " Id " << i << " --> " << pref[id][i] << endl;
//		}
		id ^= 1;
	}
	id ^= 1;
//	if (v == 1)
//		cout << v << " --> " << sz[v] << endl;
	for (int i = 0; i <= sz[v]; i++) {
		d[tp][v][i] = pref[id][i];
//		if (v == 1)
//			cout << v << " vertex " << tp << " type " << i << " with CNT is " << d[tp][v][i] << endl;
	}
	return d[tp][v][cnt];
}

int main() {
	#ifdef Nick
	freopen(fname"in","r",stdin);
	freopen(fname"out","w",stdout);
	#endif
	scanf("%d", &n);
	for (int i = 1, x, y; i < n; i++) {
		scanf("%d%d", &x, &y);
		g[x].pb(y), g[y].pb(x);
	}
	dfs(1);
	memset(d, -1, sizeof d);
	if (sz(g[1]) == 1)
		printf("%d", min(D(0, 1, sz[1] / 2 + 1), D(1, 1, sz[1] / 2 + 1)));
	else
		printf("%d", min(D(0, 1, sz[1] / 2), D(1, 1, sz[1] / 2)));
	return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define f first
#define s second
#define mp make_pair
#define sz(a) int((a).size())
#define fname "."

typedef long long ll;
typedef unsigned long long ull;

const int MAX_N = 5123;
const double eps = 1e-6;
const int inf = (int)1e9 + 123;

using namespace std;

int n;
vector < int > g[MAX_N];
int d[2][MAX_N][MAX_N];
int sz[MAX_N];

void dfs(int v, int pr = -1) {
    sz[v] = 0;
    int son = sz(g[v]);
    if (pr != -1)
        son--;
    if (!son) {
        sz[v] = 1;
        return;
    }
    for (auto to : g[v]) {
        if (to != pr) {
            dfs(to, v);
            sz[v] += sz[to];
        }
    }
}

int D(bool tp, int v, int cnt, int pr = -1) {
    int son = sz(g[v]);
    if (pr != -1)
        son--;
    if (!son && ((!tp && cnt != 0) || (tp && cnt == 0)))
        return d[tp][v][cnt] = inf;
    if (cnt > sz[v])
        return d[tp][v][cnt] = inf;
    if (!son)
        return d[tp][v][cnt] = 0;
    if (d[tp][v][cnt] != -1)
        return d[tp][v][cnt];
    int step = 0;
    for (int i = 0; i <= sz[v]; i++)
        d[tp][v][i] = inf;
    for (auto to : g[v]) {
        if (to == pr)
            continue;
        step++;
        if (step == 1) {
            for (int i = 0; i <= sz[to]; i++)
                for (int k = 0; k < 2; k++) {
                    d[tp][v][i] = min(d[tp][v][i], D(k, to, i, v) + (k != tp));
                }
        }
        else
            for (int i = sz[v], now; i >= 0; i--) {
                now = d[tp][v][i];
                d[tp][v][i] = inf;
                for (int j = 0; j <= min(i, sz[to]); j++) {
                    if (j == 0) {
                        for (int k = 0; k < 2; k++)
                            d[tp][v][i] = min(d[tp][v][i], now + D(k, to, j, v) + (k != tp));
                    }
                    else {
                        for (int k = 0; k < 2; k++)
                            d[tp][v][i] = min(d[tp][v][i], d[tp][v][i - j] + D(k, to, j, v) + (k != tp));
                    }
                }
            }
    }
    return d[tp][v][cnt];
}

int main() {
    #ifdef Nick
    freopen(fname"in","r",stdin);
    freopen(fname"out","w",stdout);
    #endif
    scanf("%d", &n);
    for (int i = 1, x, y; i < n; i++) {
        scanf("%d%d", &x, &y);
        g[x].pb(y), g[y].pb(x);
    }
    dfs(1);
    memset(d, -1, sizeof d);
    if (sz(g[1]) == 1)
        printf("%d", min(D(0, 1, sz[1] / 2 + 1), D(1, 1, sz[1] / 2)));
    else
        printf("%d", min(D(0, 1, sz[1] / 2), D(1, 1, sz[1] / 2)));
    return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define f first
#define s second
#define mp make_pair
#define sz(a) int((a).size())
#define fname "."

typedef long long ll;
typedef unsigned long long ull;

const int MAX_N = 5123;
const double eps = 1e-6;
const int inf = (int)1e9 + 123;

using namespace std;

int n;
vector < int > g[MAX_N];
int d[2][MAX_N][MAX_N];
int sz[MAX_N];

void dfs(int v, int pr = -1) {
    sz[v] = 0;
    int son = sz(g[v]);
    if (pr != -1)
        son--;
    if (!son) {
        sz[v] = 1;
        return;
    }
    for (auto to : g[v]) {
        if (to != pr) {
            dfs(to, v);
            sz[v] += sz[to];
        }
    }
}

int D(bool tp, int v, int cnt, int pr = -1) {
    int son = sz(g[v]);
    if (pr != -1)
        son--;
    if (!son && ((!tp && cnt != 0) || (tp && cnt == 0)))
        return d[tp][v][cnt] = inf;
    if (cnt > sz[v])
        return d[tp][v][cnt] = inf;
    if (!son)
        return d[tp][v][cnt] = 0;
    if (d[tp][v][cnt] != -1)
        return d[tp][v][cnt];
    int step = 0, id = 0;
    int pref[sz[v] + 5];
    for (int i = 0; i <= sz[v]; i++)
        pref[i] = inf;
    for (auto to : g[v]) {
        if (to == pr)
            continue;
        step++;
        if (step == 1) {
            for (int i = 0; i <= sz[to]; i++)
                for (int k = 0; k < 2; k++) {
                    pref[i] = min(pref[i], D(k, to, i, v) + (k != tp));
                }
        }
        else
            for (int i = sz[v], now; i >= 0; i--) {
                now = pref[i];
                pref[i] = inf;
                for (int j = 0; j <= min(i, sz[to]); j++) {
                    if (j == 0) {
                        for (int k = 0; k < 2; k++)
                            pref[i] = min(pref[i], now + D(k, to, j, v) + (k != tp));
                    }
                    else {
                        for (int k = 0; k < 2; k++)
                            pref[i] = min(pref[i], pref[i - j] + D(k, to, j, v) + (k != tp));
                    }
                }
            }
        id ^= 1;
    }
    id ^= 1;
    for (int i = 0; i <= sz[v]; i++) {
        d[tp][v][i] = pref[i];
    }
    return d[tp][v][cnt];
}

int main() {
    #ifdef Nick
    freopen(fname"in","r",stdin);
    freopen(fname"out","w",stdout);
    #endif
    scanf("%d", &n);
    for (int i = 1, x, y; i < n; i++) {
        scanf("%d%d", &x, &y);
        g[x].pb(y), g[y].pb(x);
    }
    dfs(1);
    memset(d, -1, sizeof d);
    if (sz(g[1]) == 1)
        printf("%d", min(D(0, 1, sz[1] / 2 + 1), D(1, 1, sz[1] / 2)));
    else
        printf("%d", min(D(0, 1, sz[1] / 2), D(1, 1, sz[1] / 2)));
    return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define pp pop_back
#define f first
#define s second
#define mp make_pair
#define sz(a) int((a).size())
#define fname "."

typedef long long ll;
typedef unsigned long long ull;

const int MAX_N = 5123;
const double eps = 1e-6;
const int inf = (int)1e9 + 123;

using namespace std;

int n;
vector < int > g[MAX_N];
int d[2][MAX_N][MAX_N];
int sz[MAX_N];

void dfs(int v, int pr = -1) {
    sz[v] = 0;
    int son = sz(g[v]);
    if (pr != -1)
        son--;
    if (!son) {
        sz[v] = 1;
        return;
    }
    for (auto to : g[v]) {
        if (to != pr) {
            dfs(to, v);
            sz[v] += sz[to];
        }
    }
}

int D(bool tp, int v, int cnt, int pr = -1) {
    int son = sz(g[v]);
    if (pr != -1)
        son--;
    if (!son && ((!tp && cnt != 0) || (tp && cnt == 0)))
        return d[tp][v][cnt] = inf;
    if (cnt > sz[v])
        return d[tp][v][cnt] = inf;
    if (!son)
        return d[tp][v][cnt] = 0;
    if (d[tp][v][cnt] != -1)
        return d[tp][v][cnt];
    int step = 0, id = 0;
    int pref[2][sz[v] + 5];
    for (auto to : g[v]) {
        if (to == pr)
            continue;
        for (int i = 0; i <= sz[v]; i++)
            pref[id][i] = inf;
        step++;
        if (step == 1) {
            for (int i = 0; i <= sz[to]; i++)
                for (int k = 0; k < 2; k++) {
                    pref[id][i] = min(pref[id][i], D(k, to, i, v) + (k != tp));
                }
        }
        else
            for (int i = 0; i <= sz[v]; i++)
                for (int j = 0; j <= min(i, sz[to]); j++) {
                    for (int k = 0; k < 2; k++) {
                        pref[id][i] = min(pref[id][i], pref[id ^ 1][i - j] + D(k, to, j, v) + (k != tp));
                    }
                }
        id ^= 1;
    }
    id ^= 1;
    for (int i = 0; i <= sz[v]; i++) {
        d[tp][v][i] = pref[id][i];
    }
    return d[tp][v][cnt];
}

int main() {
    #ifdef Nick
    freopen(fname"in","r",stdin);
    freopen(fname"out","w",stdout);
    #endif
    scanf("%d", &n);
    for (int i = 1, x, y; i < n; i++) {
        scanf("%d%d", &x, &y);
        g[x].pb(y), g[y].pb(x);
    }
    dfs(1);
    memset(d, -1, sizeof d);
    if (sz(g[1]) == 1)
        printf("%d", min(D(0, 1, sz[1] / 2 + 1), D(1, 1, sz[1] / 2)));
    else
        printf("%d", min(D(0, 1, sz[1] / 2), D(1, 1, sz[1] / 2)));
    return 0;
}


/**
 * Codeforces
 * Problem#581F
 * Accepted
 * Time: 139ms
 * Memory: 198380k
 */
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;
#define smin(_a, _b) (_a = min(_a, _b))

const int N = 5005;

int n;
vector<int> *g;
// 0: black, 1: white
int f[N][N][2];    // node, number of the black nodes, the color of this node
int temp[N][2];
int root;
int clf[N];
int deg[N];

inline void init() {
    scanf("%d", &n);
    g = new vector<int>[(n + 1)];
    for(int i = 1, u, v; i < n; i++) {
        scanf("%d%d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
        deg[u]++, deg[v]++;
    }
    for(root = 1; root < n && deg[root] == 1; root++);
}

void treedp(int node, int fa) {
    if(deg[node] == 1) {
        f[node][1][0] = f[node][0][1] = 0;
        f[node][1][1] = f[node][0][0] = 1;
        clf[node] = 1;
        return;
    }
//    memset(temp)
    clf[node] = 0;
    f[node][0][0] = f[node][0][1] = 0;
    for (int i = 0; i < deg[node]; i++) {
        int e = g[node][i];
        if (e == fa)    continue;
        treedp(e, node);
        memset(temp, 0x3f, sizeof(temp));
        for (int s1 = clf[node]; ~s1; s1--) {
            for (int s2 = clf[e]; ~s2; s2--) {
                smin(temp[s1 + s2][0], f[node][s1][0] + min(f[e][s2][0], f[e][s2][1] + 1));
                smin(temp[s1 + s2][1], f[node][s1][1] + min(f[e][s2][0] + 1, f[e][s2][1]));
            }
        }
        clf[node] += clf[e];
        for (int j = 0; j <= clf[node]; j++)
            f[node][j][0] = temp[j][0], f[node][j][1] = temp[j][1];
    }
}

inline void solve() {
    memset(f, 0x3f, sizeof(f));
    treedp(root, 0);
    int k = (n-1) >> 1;
    int ans = min(f[root][k][0], f[root][k][1]);
    printf("%d\n", ans);
}

int main() {
    init();
    solve();
    return 0;
}