#include <bits/stdc++.h>
using namespace std;
static const int MAXN = 5005;
static int dp[MAXN][MAXN][2];
vector<int> edges[MAXN];
vector<int> straight[MAXN];
static int n, root, leaf;
int vis[MAXN];
int par[MAXN];
int aft[MAXN];
int subleaf[MAXN];
void dfs(int node, int p = 0) {
  if (edges[node].size() == 1) subleaf[node] = 1;
  vis[node] = 1;
  par[node] = p;
  for (int g : edges[node]) {
    if (vis[g]) continue;
    dfs(g, node);
    subleaf[node] += subleaf[g];
  }
}
int gc(int node) {
  if (node == root) return edges[node].size();
  return edges[node].size() - 1;
}
int solve(int node, int cl, int col) {
  if (cl < 0) return 1e9;
  if (cl > subleaf[par[node]]) return 1e9;
  if (dp[node][cl][col] != -1) return dp[node][cl][col];
  int st = cl;
  dp[node][cl][col] = 1e9;
  if (aft[node] == 0) {
    if (straight[node].size() == 0) {
      if (st >= 2)
        return dp[node][cl][col] = 1e9;
      else if (st == 1)
        return dp[node][cl][col] = ((col == 0) ? (0) : (1));
      return dp[node][cl][col] = ((col == 0) ? (1) : (0));
    }
    return dp[node][cl][col] =
               min(dp[node][cl][col],
                   min(solve(straight[node][0], st, col),
                       1 + solve(straight[node][0], st, 1 - col)));
  }
  if (edges[node].size() == 1) {
    if (st == 0)
      return dp[node][cl][col] = (col == 0) + solve(aft[node], st, col);
    return dp[node][cl][col] = min(solve(aft[node], st - (col == 0), col),
                                   1 + solve(aft[node], st - (col == 1), col));
  }
  for (int g = 0; g <= min(st, subleaf[node]); g++) {
    int T = min(solve(straight[node][0], g, 1 - col) + 1,
                solve(straight[node][0], g, col)) +
            solve(aft[node], st - g, col);
    if (T < dp[node][cl][col]) dp[node][cl][col] = T;
  }
  return dp[node][cl][col];
}
int main() {
  memset(dp, -1, sizeof(dp));
  ios_base::sync_with_stdio(0);
  cin >> n;
  for (int g = 0; g < n - 1; g++) {
    int a, b;
    cin >> a >> b;
    edges[a].push_back(b);
    edges[b].push_back(a);
  }
  for (int g = 1; g <= n; g++)
    if (edges[g].size() == 1) leaf++;
  if (leaf == 2) {
    cout << 1;
    return EXIT_SUCCESS;
  }
  for (int g = 1; g <= n; g++)
    if (edges[g].size() != 1) root = g;
  dfs(root);
  memset(vis, 0, sizeof(vis));
  for (int g = 1; g <= n; g++) {
    for (int y : edges[g]) {
      if (y == par[g]) continue;
      straight[g].push_back(y);
    }
  }
  for (int g = 1; g <= n; g++) {
    for (int y = straight[g].size() - 2; y >= 0; y--) {
      aft[straight[g][y]] = straight[g][y + 1];
    }
  }
  memset(vis, 0, sizeof(vis));
  cout << min(solve(edges[root][0], leaf / 2, 0),
              solve(edges[root][0], leaf / 2, 1))
       << '\n';
  return EXIT_SUCCESS;
}
