You have unweighted tree of n vertices. You have to assign a positive weight to each edge so that the following condition would hold:

  * For every two different leaves v_{1} and v_{2} of this tree, [bitwise XOR](https://en.wikipedia.org/wiki/Bitwise_operation#XOR) of weights of all edges on the simple path between v_{1} and v_{2} has to be equal to 0. 



Note that you can put very large positive integers (like 10^{(10^{10})}).

It's guaranteed that such assignment always exists under given constraints. Now let's define f as the number of distinct weights in assignment.

<image> In this example, assignment is valid, because bitwise XOR of all edge weights between every pair of leaves is 0. f value is 2 here, because there are 2 distinct edge weights(4 and 5).

<image> In this example, assignment is invalid, because bitwise XOR of all edge weights between vertex 1 and vertex 6 (3, 4, 5, 4) is not 0. 

What are the minimum and the maximum possible values of f for the given tree? Find and print both.

Input

The first line contains integer n (3 ≤ n ≤ 10^{5}) — the number of vertices in given tree.

The i-th of the next n-1 lines contains two integers a_{i} and b_{i} (1 ≤ a_{i} < b_{i} ≤ n) — it means there is an edge between a_{i} and b_{i}. It is guaranteed that given graph forms tree of n vertices.

Output

Print two integers — the minimum and maximum possible value of f can be made from valid assignment of given tree. Note that it's always possible to make an assignment under given constraints.

Examples

Input


6
1 3
2 3
3 4
4 5
5 6


Output


1 4


Input


6
1 3
2 3
3 4
4 5
4 6


Output


3 3


Input


7
1 2
2 7
3 4
4 7
5 6
6 7


Output


1 6

Note

In the first example, possible assignments for each minimum and maximum are described in picture below. Of course, there are multiple possible assignments for each minimum and maximum. 

<image>

In the second example, possible assignments for each minimum and maximum are described in picture below. The f value of valid assignment of this tree is always 3. 

<image>

In the third example, possible assignments for each minimum and maximum are described in picture below. Of course, there are multiple possible assignments for each minimum and maximum. 

<image>
import java.io.*;
import java.util.*;
import java.math.*;

 
 public class Main	{
	static class node{
		int a, b;
		public node(int x, int y) {
			a = x;
			b = y;
		}
	}
   static class Pair implements Comparable<Pair>{

	   int a;
	   int b;
//	   int ind;
//	   public Pair(int x, long y) {a = x;b=y;}
	   public Pair(int x, int y) {a = x;b=y;}
//	   public Pair(int x,int y, int z){a=x;b=y;ind = z;}
	   public int compareTo(Pair p){
		   if(a == p.a)
			   return b - p.b;
		   else
			   return a - p.a;
	   }
//		@Override
//		public int hashCode() {
//			final int prime = 31;
//			int result = 1;
//			result = prime * result + a;
//			result = prime * result + b;
//		   
//			return result;
//		}
//		@Override
//		public boolean equals(Object obj) {
//			Pair cur = (Pair)obj;
//			if((a==cur.a && b==cur.b))return true;
//			return false;
//		}
 } 

public static void main(String[] args) throws Exception {
   new Thread(null, null, "Anshum Gupta", 99999999) {
        public void run() {
            try {
                solve();
            } catch(Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
    }.start();
}
public static long gcd(long a,long b)
{
  if(a<b)
    return gcd(b,a);
  if(b==0)
    return a;
  return gcd(b,a%b);
  
}
static long lcm(int a,int b) {
  return  a*b / gcd(a,b);
}
    
static long pow(long x,long y){
    if(y == 0)return 1;
    if(y==1)return x;
    long a = pow(x,y/2);
    a = (a*a)%mod;
    if(y%2==0){
        return a;
    }
    return (a*x)%mod;
}

static long[]fact,inv_fact;
static long my_inv(long a) {
	return pow(a,mod-2);
}
static long bin(int a,int b) {
	if(a < b || a<0 || b<0)return 0;
    return ((fact[a]*inv_fact[a-b])%mod * inv_fact[b])%mod;
}
	
static void make_facts() {
  fact=new long[mxN];
  inv_fact = new long[mxN];
  fact[0]=inv_fact[0]=1L;
  for(int i=1;i<mxN;i++) {
	   fact[i] = (i*fact[i-1])%mod;
	   inv_fact[i] = my_inv(fact[i]);
  }
}
static void lazy(int st, int e, int tn) {
	if(lazy[tn] != INF) {
		tree[tn] = Math.min(tree[tn], lazy[tn]);
		if(st != e) {
			lazy[2*tn] = Math.min(lazy[2*tn], lazy[tn]);
			lazy[2*tn+1] = Math.min(lazy[2*tn+1], lazy[tn]);
		}
		lazy[tn] = INF;
	}
}
static void update(int ind, int val, int st, int e, int tn) {
	if(st == e) {
		tree[tn] = val;
		return;
	}
	int mid = (st + e) >> 1;	
  	if(ind <= mid)
		update(ind, val, st, mid, 2*tn);
  	else
		update(ind, val, mid+1, e, 2*tn+1);
	tree[tn] = Math.min(tree[2*tn], tree[2*tn+1]);
}
static int query(int l, int r, int st, int e, int tn) {
	if(st > r || e < l)return INF;
	
	if(st >= l && e <= r) {
		return tree[tn];
	}

	int mid = (st + e) >> 1;
	int x = query(l, r, st, mid, 2 * tn);
	int y = query(l, r, mid+1, e, 2 * tn + 1);
	return Math.min(x, y);
}
static final long mxx = (long)(1e18+5);
static final int mxN = (int)(1e5);
static final int mxV = (int)(1e5+5);
static final long mod = (long)(1e9+7); //998244353;//
static int[]tree, lazy;
static final int INF = (int)1e9+5;
static ArrayList<ArrayList<Integer>> adj;
static int n, m, q, t, k, l, p, c1, c2, ansmin, ansmax;
static int[]a, odd, even, leaf, dist;
static void dfs(int par, int cur) {
	leaf[cur] = 1;
	dist[cur] = dist[par] + 1;
	int nrl = 0;
	for(Integer x : adj.get(cur)) {
		if(x == par)continue;
		dfs(cur, x);
		leaf[cur] = 0;
		nrl += leaf[x];
		odd[cur] |= even[x];
		even[cur] |= odd[x];
	}
	ansmax -= Math.max(0, nrl - 1);
	if(odd[cur] > 0 && even[cur] > 0)
		ansmin = 3;
	if(leaf[cur] > 0)
		even[cur] = 1;
}
	public static void solve() throws Exception {
   // solve the problem here
   MyScanner s = new MyScanner();
        out = new PrintWriter(new BufferedOutputStream(System.out), true);
        int tc = 1;//s.nextInt();
        
        while(tc-->0){
        	n = s.nextInt();
        	adj = new ArrayList<ArrayList<Integer>>();
        	for(int i=0; i<=n; i++)adj.add(new ArrayList<Integer>());
        	for(int i=0; i<n-1; i++) {
        		int a = s.nextInt();
        		int b = s.nextInt();
        		adj.get(a).add(b);
        		adj.get(b).add(a);
        	}
        	int root = 0;
        	for(int i=1; i<=n; i++) {
        		if(adj.get(i).size() != 1) {
        			root = i;
        			break;
        		}
        	}
        	leaf = new int[n+1];
        	odd = new int[n+1];
        	even = new int[n+1];
        	dist = new int[n+1];
        	ansmax = n - 1;
        	ansmin = 1;
        	dfs(0, root);
        	out.println(ansmin + " " + ansmax);
        }
        	
           
        out.flush();
}
 
     
 
 
 
    //-----------PrintWriter for faster output---------------------------------
    public static PrintWriter out;
 
    //-----------MyScanner class for faster input----------
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
 
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
 
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
 
        int nextInt() { return Integer.parseInt(next()); }
        long nextLong() { return Long.parseLong(next()); }
        double nextDouble() { return Double.parseDouble(next()); }
         
        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
    //--------------------------------------------------------
}
