#include <bits/stdc++.h>
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("-O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,tune=native")
using namespace std;
const int N = 5050;
int down[N], up[N], par[N];
int can[N][N];
vector<vector<int> > g(N);
void dfs(int v, int pr) {
  for (auto i : g[v]) {
    if (i == pr) {
      continue;
    }
    dfs(i, v);
    down[v] += down[i];
  }
  down[v] += 1;
  if (v != 1) {
    up[v] = up[pr] + down[pr] - down[v];
  }
  par[v] = pr;
}
void dfs2(int v, int pr) {
  if (v != 1) {
    up[v] = up[pr] + down[pr] - down[v];
  }
  for (auto i : g[v]) {
    if (i == pr) {
      continue;
    }
    dfs2(i, v);
  }
}
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin >> n;
  for (int i = 1; i < n; i++) {
    int u, v;
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  cout << "\n";
  dfs(1, 1);
  dfs2(1, 1);
  set<pair<int, int> > s;
  for (int v = 1; v <= n; v++) {
    vector<int> a;
    a.push_back(0);
    for (auto to : g[v]) {
      if (to == par[v]) {
        continue;
      }
      a.push_back(down[to]);
    }
    if (v != 1) {
      a.push_back(up[v]);
    }
    can[0][0] = 1;
    for (int i = 1; i < a.size(); i++) {
      for (int j = 0; j < (n + 1) / 2; j++) {
        can[i][j] = can[i - 1][j];
        if (j >= a[i]) {
          can[i][j] |= can[i - 1][j - a[i]];
        }
        if (can[i][j] && j > 0) {
          s.insert({j, n - 1 - j});
          s.insert({n - 1 - j, j});
        }
      }
    }
    for (int i = 1; i < a.size(); i++) {
      for (int j = 0; j < (n + 1) / 2; j++) {
        can[i][j] = 0;
      }
    }
  }
  cout << s.size() << "\n";
  while (s.size() > 0) {
    pair<int, int> p = *s.begin();
    s.erase(s.begin());
    cout << p.first << " " << p.second << "\n";
  }
}
