#include<bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i = (int)(a); i <= (int)(b); i++)
#define NFOR(i,a,b) for(int i = (int)(a); i >= (int)(b); --i)
#define endl "\n"
#define mp make_pair
#define X first
#define Y second
#define inf 1e9
#define mod 1000000007
#define pb push_back
#define Case cout<<"Case #"<<++cas<<": ";
#define fastio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define all(v) v.begin(),v.end()
#define sz(x) int(x.size())
// #define lli int
typedef long long int lli;
typedef long long ll;
typedef pair<int,int> pii;
typedef vector<pii> vii;
typedef pair<lli,lli> pll;
typedef vector<lli> vl;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef complex <long double> complex_t;
const long double PI = acos((long double)-1.0);

#define pr(...) dbs(#__VA_ARGS__, __VA_ARGS__)
template <class T> void dbs(string str, T t) {cerr << str << " : " << t << "\n";}
template <class T, class... S> void dbs(string str, T t, S... s) {int idx = str.find(','); cerr << str.substr(0, idx) << " : " << t << ","; dbs(str.substr(idx + 1), s...);}
template <class S, class T>ostream& operator <<(ostream& os, const pair<S, T>& p) {return os << "(" << p.first << ", " << p.second << ")";}
template <class T>ostream& operator <<(ostream& os, const vector<T>& p) {os << "[ "; for (auto& it : p) os << it << " "; return os << "]";}
template <class T>ostream& operator <<(ostream& os, const set<T>& p) {os << "[ "; for (auto& it : p) os << it << " "; return os << "]";}
template <class S, class T>ostream& operator <<(ostream& os, const map<S, T>& p) {os << "[ "; for (auto& it : p) os << it << " "; return os << "]";}
template <class T> void prc(T a, T b) {cerr << "["; for (T i = a; i != b; ++i) {if (i != a) cerr << ", "; cerr << *i;} cerr << "]\n";}

ll dp[100010];
bool visited[100010];
vi Adj[100010];
int n; 
int limitDist;
bool flag;

bool verify(int posToAvoid, vi &listOfdP) {
    vi res;
    FOR(i, 0, sz(listOfdP)-1) {
        if (posToAvoid != i) {
            res.pb(listOfdP[i]);
        }
    }
    FOR(i, 0, sz(res)-1) {
        if (res[i] + res[sz(res)-1-i] > limitDist) return false; 
    }
    return true;
}

void DFS(int u, int p) {
    dp[u] = 1e8;
    for (auto v : Adj[u]) {
        if (v != p) {
            DFS(v, u);
        }
    }
    vi listOfdP;
    for (auto v : Adj[u]) {
        if (v != p) {
            listOfdP.pb(dp[v]);
        }
    }
    if ((sz(Adj[u])-1)%2==0) {
        listOfdP.pb(0);
    }
    int l1 = 0, h1 = sz(listOfdP)-1;
    sort(all(listOfdP));
    while ( l1 < h1) {
        int mid = (l1 + h1)/2;
        if (l1 + 1 == h1) {
            if (verify(l1, listOfdP)) h1 = l1;
            else l1 = h1;
            break;
        }
        if (verify(mid, listOfdP)) {
            h1 = mid;
        } else {
            l1 = mid;
        }
    }
    // pr(l1, h1);
    assert(l1 == h1);
    if (verify(l1, listOfdP)) {
        dp[u] = listOfdP[l1] + 1;
    }
    // pr(u, dp[u]);
}

bool isValid(int root, int p, int dist) {
    FOR(i, 0, n) {
        dp[i] = 0, visited[i] = false;
    }
    limitDist = dist;
    // pr(dist);
    DFS(root, p);
    if (dp[root] <= dist+1) return true;
    else return false;
}

int main() {
    cin >> n;
    FOR(i, 1, n-1) {
        int a1, b1;
        cin >> a1 >> b1;
        Adj[a1].pb(b1), Adj[b1].pb(a1);
    }
    int root = -1;
    int countOdd = 0;
    FOR(i, 1, n) {
        if (sz(Adj[i]) == 1) root = i;
    }
    FOR(i, 1, n) {
        if (sz(Adj[i])%2 == 1) countOdd++;
    }
    int l = 1;
    int h = n;
    while (l < h) {
        int mid = (l+h)/2;
        if (l+1==h) {
            if (isValid(root, 0, l)) h = l;
            else l = h;
            break;
        }
        if (isValid(root, 0, mid)) {
            h = mid;
        } else {
            l = mid+1;
        }
    }
    cout << countOdd/2 << " " << l << endl;
return 0;}

Measured memory_bytes: 19072