#include <stdio.h>
#include <string.h>
#include <bits/stdc++.h>
using namespace std;
#define ll long long 

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);
}


template< typename G >
struct DoublingLowestCommonAncestor {
	const int LOG;
	vector< int > dep;
	const G& g;
	vector< vector< int > > table;

	DoublingLowestCommonAncestor(const G& g) : g(g), dep(g.size()), LOG(32 - __builtin_clz(g.size())) {
		table.assign(LOG, vector< int >(g.size(), -1));
	}

	void dfs(int idx, int par, int d) {
		table[0][idx] = par;
		dep[idx] = d;
		for (auto& to : g[idx]) {
			if (to != par) dfs(to, idx, d + 1);
		}
	}

	void build() {
		dfs(0, -1, 0);
		for (int k = 0; k + 1 < LOG; k++) {
			for (int i = 0; i < table[k].size(); i++) {
				if (table[k][i] == -1) table[k + 1][i] = -1;
				else table[k + 1][i] = table[k][table[k][i]];
			}
		}
	}

	int query(int u, int v) {
		if (dep[u] > dep[v]) swap(u, v);
		for (int i = LOG - 1; i >= 0; i--) {
			if (((dep[v] - dep[u]) >> i) & 1) v = table[i][v];
		}
		if (u == v) return u;
		for (int i = LOG - 1; i >= 0; i--) {
			if (table[i][u] != table[i][v]) {
				u = table[i][u];
				v = table[i][v];
			}
		}
		return table[0][u];
	}
};

bool check[100005];

int main() {

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


	int n, u, v;
	cin >> n >> u >> v;
	u--;
	v--;
	
	WeightedGraph< int > g(100005);
	UnWeightedGraph g2(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);
		g2[x].push_back(y);
		g2[y].push_back(x);
	}
	//cout << "a" << endl;

	queue<int> que;
	que.push(u);

	vector<int> dist(100005, INF);
	dist[u] = 0;

	while (!que.empty()) {

		int now = que.front();
		que.pop();
		if (check[now] == 1)continue;
		check[now] = 1;

		for (int nxt : g[now]) {

			if (check[nxt] == 0) {

				if (dist[nxt] > dist[now] + 1) {
					dist[nxt] = dist[now] + 1;
					que.push(nxt);
				}
			}
		}
	}


	DoublingLowestCommonAncestor< UnWeightedGraph > lca(g2);
	lca.build();


	int common = lca.query(u, v);
	int diameter = tree_diameter(g);
	if (abs(dist[u] - dist[common]) > abs(dist[v] - dist[common])) {

		cout << diameter - 1 << endl;

	}
	else
	{
		cout << dist[v] - 1 << endl;
	}


	return 0;
}

