#include<algorithm>
#include<bitset>
#include<cassert>
#include<cfloat>
#include<climits>
#include<cmath>
#include<deque>
#include<functional>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<string>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<vector>
#include<complex>

#define REP(i, n) for(int i = 0;i < n;i++)
#define REPR(i, n) for(int i = n;i >= 0;i--)
#define FOR(i, m, n) for(int i = m;i < n;i++)
#define FORR(i, m, n) for(int i = m;i >= n;i--)
#define SORT(v, n) sort(v, v+n);
#define VSORT(v) sort(v.begin(), v.end());
#define llong long long
#define pb(a) push_back(a)

using namespace std;

typedef long long int ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<typename T>
vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T, typename... Ts>
auto make_v(size_t a, Ts... ts) {
	return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}
template<typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type
fill_v(T& t, const V& v) { t = v; }
template<typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type
fill_v(T& t, const V& v) {
	for (auto& e : t) fill_v(e, v);
}


#define ARRAY_MAX 100005
const int INF = INT32_MAX / 3;
const ll MOD = 1e9 + 7;

int dx[4] = { 0,1,0,-1 };
int dy[4] = { 1,0,-1,0 };


/******************************************************************************************/

template< typename T >
struct edge {
	int src, to;
	T cost;

	edge(int to, T cost) : src(-1), to(to), cost(cost) {}

	edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

	edge& operator=(const int& x) {
		to = x;
		return *this;
	}

	operator int() const { return to; }
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedGraph = vector< Edges< T > >;
using UnWeightedGraph = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;


template< typename T >
pair< T, int > dfs(const WeightedGraph< T >& g, int idx, int par) {
	pair< T, int > ret(0, idx);
	for (auto& e : g[idx]) {
		if (e.to == par) continue;
		auto cost = dfs(g, e.to, idx);
		cost.first += e.cost;
		ret = max(ret, cost);
	}
	return ret;
}

template< typename T >
T tree_diameter(const WeightedGraph< T > & g) {
	auto p = dfs(g, 0, -1);
	auto q = dfs(g, p.second, -1);
	return (q.first);
}


int main() {

	cin.tie(0);
	ios::sync_with_stdio(false);
	cout << fixed << setprecision(10);


	int n, u, v;
	cin >> n >> u >> v;
	
	WeightedGraph< int > g(100005);
	for (int i = 0; i < n - 1; i++) {
		//cout << "i= " << i << endl;
		int x, y;
		cin >> x >> y;
		x--;
		y--;
		g[x].emplace_back(y,1);
		g[y].emplace_back(x,1);
	}
	//cout << "a" << endl;
	printf("%d\n", tree_diameter(g)-1);

	return 0;
}
