#include <bits/stdc++.h>
using namespace std;
int n, i, x, y, lsum = 1, root, tot, Ans1, Ans2;
int head[400010], f[400010], size[400010], d[400010], p[400010], l[400010],
    g[400010], o[400010];
vector<int> son[400010];
map<int, int> M;
struct Edge {
  int t, next, l;
} e[400010 * 8];
inline int Find(int x) { return (x == p[x]) ? x : p[x] = Find(p[x]); }
inline void Add(int s, int t) {
  e[lsum].t = t;
  e[lsum].next = head[s];
  head[s] = lsum++;
}
inline int Abs(int x) { return (x < 0) ? -x : x; }
inline void Swap(int &a, int &b) { a ^= b ^= a ^= b; }
inline int Min(int a, int b) { return (a < b) ? a : b; }
inline int Max(int a, int b) { return (a > b) ? a : b; }
inline int read() {
  int p = 0, f = 1;
  char c = getchar();
  while (c < 48 || c > 57) {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= 48 && c <= 57) p = (p << 1) + (p << 3) + c - 48, c = getchar();
  return p * f;
}
inline void Maketree(int x, int fa) {
  int i = 0;
  size[x] = 1;
  for (i = head[x]; i; i = e[i].next) {
    if (e[i].t == fa) continue;
    f[e[i].t] = x;
    son[x].push_back(e[i].t);
    Maketree(e[i].t, x);
    size[x] += size[e[i].t];
  }
}
inline void Dfs(int x) {
  if (!son[x].size()) {
    o[p[x]] = 1;
    return;
  }
  for (auto i : son[x]) {
    Dfs(i);
    g[p[x]] += o[p[i]];
    o[p[x]] += g[p[i]];
  }
  if (g[p[x]] && o[p[x]]) Ans1 = 3;
}
int main() {
  n = read();
  for (i = 1; i < n; i++) {
    x = read();
    y = read();
    Add(x, y);
    Add(y, x);
    d[x]++;
    d[y]++;
  }
  for (i = 1; i <= n; i++)
    if (d[i] > 1) {
      root = i;
      break;
    }
  Maketree(root, 0);
  for (i = 1; i <= n; i++) p[i] = n + i;
  for (i = 1; i <= n; i++)
    if (!son[i].size()) p[i] = p[f[i]];
  for (i = 1; i <= n; i++)
    if (p[i] == n + i) p[i] = i;
  for (i = 1; i <= n; i++)
    if (!M[p[i]]) Ans2++, M[p[i]]++;
  Ans1 = 1;
  Dfs(root);
  printf("%d %d\n", Ans1, Ans2 - 1);
  return 0;
}
