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

const int MAXN = 1.1e5;
int N;
vector<int> adj[MAXN];
vector<int> order;

void dfs(int cur, int prv) {
	if (prv != -1) {
		adj[cur].erase(find(adj[cur].begin(), adj[cur].end(), prv));
	}
	for (int nxt : adj[cur]) {
		dfs(nxt, cur);
	}
	order.push_back(cur);
}

int bestUp[MAXN];

bool isGood(int v) {
	auto pairUp = [&](const vector<int>& vals) -> bool {
		int i = 0, j = int(lower_bound(vals.begin(), vals.end(), v) - vals.begin());
		int extraCnt = int(vals.size()) - j;
		j--;
		for (; i <= j; i++) {
			if (i < j && vals[i]+vals[j] >= v) {
				j--;
			} else {
				if (extraCnt == 0) return false;
				extraCnt--;
			}
		}
		return true;
	};
	for (int cur : order) {
		vector<int> ch; ch.reserve(adj[cur].size());
		for (int nxt : adj[cur]) {
			ch.push_back(bestUp[nxt]+1);
		}
		sort(ch.begin(), ch.end());

		if (cur == 0) {
			return pairUp(ch);
		}

		int mi = -1, ma = int(ch.size());
		while (ma - mi > 1) {
			int md = (mi + ma) / 2;
			vector<int> nch = ch;
			nch.erase(nch.begin()+md);
			if (pairUp(nch)) {
				mi = md;
			} else {
				ma = md;
			}
		}
		if (mi >= 0) {
			bestUp[cur] = ch[mi];
		} else if (pairUp(ch)) {
			bestUp[cur] = 0;
		} else {
			return false;
		}
	}
	assert(false);
}

int main() {
	ios_base::sync_with_stdio(0); cin.tie(0);

	cin >> N;
	for (int e = 0; e < N-1; e++) {
		int a, b; cin >> a >> b; a--, b--;
		adj[a].push_back(b);
		adj[b].push_back(a);
	}

	order.reserve(N);
	dfs(0, -1);

	int mi = 1, ma = N;
	while (ma - mi > 1) {
		int md = (mi + ma) / 2;
		if (isGood(md)) {
			mi = md;
		} else {
			ma = md;
		}
	}
	cout << mi << '\n';

	return 0;
}
