Problem:
Score : 1400 points

Problem Statement

We will recursively define uninity of a tree, as follows: (Uni is a Japanese word for sea urchins.)

A tree consisting of one vertex is a tree of uninity 0.

Suppose there are zero or more trees of uninity k, and a vertex v. If a vertex is selected from each tree of uninity k and connected to v with an edge, the resulting tree is a tree of uninity k+1.

It can be shown that a tree of uninity k is also a tree of uninity k+1,k+2,..., and so forth.

You are given a tree consisting of N vertices.
The vertices of the tree are numbered 1 through N, and the i-th of the N-1 edges connects vertices a_i and b_i.

Find the minimum k such that the given tree is a tree of uninity k.

Constraints

2 ≦ N ≦ 10^5

1 ≦ a_i, b_i ≦ N(1 ≦ i ≦ N-1)

The given graph is a tree.

Input

The input is given from Standard Input in the following format:

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

Output

Print the minimum k such that the given tree is a tree of uninity k.

Sample Input 1

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

Sample Output 1

2

A tree of uninity 1 consisting of vertices 1, 2, 3 and 4 can be constructed from the following: a tree of uninity 0 consisting of vertex 1, a tree of uninity 0 consisting of vertex 3, a tree of uninity 0 consisting of vertex 4, and vertex 2.

A tree of uninity 1 consisting of vertices 5 and 7 can be constructed from the following: a tree of uninity 1 consisting of vertex 5, and vertex 7.

A tree of uninity 2 consisting of vertices 1, 2, 3, 4, 5, 6 and 7 can be constructed from the following: a tree of uninity 1 consisting of vertex 1, 2, 3 and 4, a tree of uninity 1 consisting of vertex 5 and 7, and vertex 6.

Sample Input 2

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

Sample Output 2

3

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> pii;
const int N = 1e5 + 100, inF = N;

int n, u, v, ans = inF, down[N], up[N];
bool mark[N];
vector<int> nei[N];

void find_down(int v, vector<int> *vec, int par = -1) {
	down[v] = 0;
	(*vec).push_back(v);
	for (int u: nei[v])
		if(u != par && mark[u] == false) {
			find_down(u, vec, v);
			down[v] = max(down[v], down[u] + 1);
		}
}

void find_up(int v, int par = -1) {
	pii mx1 = pii(up[v] + 1, v), mx2 = pii(-inF, -inF);
	for (int u: nei[v])
		if(u != par && mark[u] == false) {
			mx2 = max(mx2, pii(down[u] + 2, u));
			if(mx2 > mx1)
				swap(mx2, mx1);
		}
	for (int u: nei[v])
		if(u != par && mark[u] == false) {
			if(u != mx1.second)
				up[u] = mx1.first;
			else
				up[u] = mx2.first;
			find_up(u, v);
		}
}

int solve(int v) {//cerr << "solving " << v + 1 << '\n';
	vector<int> vec;
	find_down(v, &vec);
	if(vec.size() == 1)
		return 0;
	up[v] = 0;
	find_up(v);
	//for (int u: vec)
	//	cerr << u + 1 << " -> " << up[u] << ' ' << down[u] << '\n';
	int mini = N, cen;
	for (int u: vec)
		if(max(up[u], down[u]) < mini) {
			mini = max(up[u], down[u]);
			cen = u;
		}
	//cerr << mini << " cen = " << cen + 1 << '\n';
	mark[cen] = true;
	int maxi = 0;
	for (int u: nei[cen])
		if(mark[u] == false)
			maxi = max(maxi, solve(u));
	return maxi + 1;
}

int main() {
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> n;
	for (int i = 0; i < n - 1; i++) {
		cin >> u >> v;
		nei[--u].push_back(--v);
		nei[v].push_back(u);
	}
	cout << solve(0);
	return 0;
}