Problem:
Score : 900 points

Problem Statement

Takahashi has decided to make a Christmas Tree for the Christmas party in AtCoder, Inc.

A Christmas Tree is a tree with N vertices numbered 1 through N and N-1 edges, whose i-th edge (1\leq i\leq N-1) connects Vertex a_i and b_i.

He would like to make one as follows:

Specify two non-negative integers A and B.

Prepare A Christmas Paths whose lengths are at most B. Here, a Christmas Path of length X is a graph with X+1 vertices and X edges such that, if we properly number the vertices 1 through X+1, the i-th edge (1\leq i\leq X) will connect Vertex i and i+1.

Repeat the following operation until he has one connected tree:

Select two vertices x and y that belong to different connected components. Combine x and y into one vertex. More precisely, for each edge (p,y) incident to the vertex y, add the edge (p,x). Then, delete the vertex y and all the edges incident to y.

Properly number the vertices in the tree.

Takahashi would like to find the lexicographically smallest pair (A,B) such that he can make a Christmas Tree, that is, find the smallest A, and find the smallest B under the condition that A is minimized.

Solve this problem for him.

Constraints

2 \leq N \leq 10^5

1 \leq a_i,b_i \leq N

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

N
a_1 b_1
:
a_{N-1} b_{N-1}

Output

For the lexicographically smallest (A,B), print A and B with a space in between.

Sample Input 1

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

Sample Output 1

3 2

We can make a Christmas Tree as shown in the figure below:

Sample Input 2

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

Sample Output 2

2 5

Sample Input 3

10
1 2
2 3
3 4
2 5
6 5
6 7
7 8
5 9
10 5

Sample Output 3

3 4

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.util.*;

public class Main {
	static class Tree {
		public class Edge {
			int to, rev;

			public Edge(int to, int rev) {
				this.to = to;
				this.rev = rev;
			}
		}
		
		int V;
		ArrayList<ArrayList<Edge>> G;
		int root;
		int[] p;
		
		public Tree(int[] a, int[] b) {
			this.V = a.length+1;
			p = new int[V];
			
			G = new ArrayList<ArrayList<Edge>>();
			for(int i=0; i<V; i++) {
				G.add(new ArrayList<Edge>());
			}
			
			for(int i=0; i<V-1; i++) {
				G.get(a[i]).add(new Edge(b[i], G.get(b[i]).size()));
				G.get(b[i]).add(new Edge(a[i], G.get(a[i]).size()-1));
			}
			setRoot(0);
		}
		
		public void setRoot(int root) {
			this.root = root;
			setRoot(root, -1);
		}
		public void setRoot(int cur, int parent) {
			p[cur] = parent;
			for(int i=0; i<G.get(cur).size(); i++) {
				int next = G.get(cur).get(i).to;
				if(next!=parent) {
					setRoot(next, cur);
				}
			}
		}
		public int countPath() {
			int ans = 0;
			for(ArrayList<Edge> node : G) {
				ans += node.size()%2;
			}
			return ans/2;
		}
		
		public boolean check(int B) {
			return dp(root, B)<=B;
		}
		
		int dp(int cur, int B) {
			ArrayList<Integer> dp = new ArrayList<>();
			for(int i=0; i<G.get(cur).size(); i++) {
				int next = G.get(cur).get(i).to;
				if(next!=p[cur]) {
					dp.add(dp(next, B)+1);
				}
			}
			Collections.sort(dp);
			if(dp.size()>0 && dp.get(dp.size()-1)>B)
				return B+1;

			if(dp.size()%2==0) {
				if(validatePairing(dp, B, -1)) {
					return 0;
				} else {
					dp.remove(dp.size()-1);
					return leaveShortestPath(dp, B);
				}
			} else {
				return leaveShortestPath(dp, B);
			}
		}
		
		int leaveShortestPath(ArrayList<Integer> v, int B) {
			int N = v.size();
			int min = -1;
			int max = N;
			while(min+1<max) {
				int skip = (min+max)/2;
				if(validatePairing(v, B, skip))
					max = skip;
				else
					min = skip;
			}
			if(max<N)
				return v.get(max);
			else
				return B+1;
		}
		
		boolean validatePairing(ArrayList<Integer> v, int B, int skip) {
			for(int i=0,j=v.size()-1; i<j; i++,j--) {
				if(i==skip)
					i++;
				if(j==skip)
					j--;
				if(v.get(i) + v.get(j) > B)
					return false;
			}
			
			return true;
		}
	}
	

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();
		int[] a = new int[N-1];
		int[] b = new int[N-1];
		for(int i=0; i<N-1; i++) {
			a[i] = sc.nextInt()-1;
			b[i] = sc.nextInt()-1;
		}
		Tree tree = new Tree(a, b);
		
		int A = tree.countPath();
		int min = 0;
		int max = N-1;
		while(min+1 < max) {
			int mid = (min+max)/2;
			if(tree.check(mid))
				max = mid;
			else
				min = mid;
		}
		
		System.out.println(A + " " + max);
		sc.close();
	}
}