#include <bits/stdc++.h>
#define WHOLE(v) (v).begin(), (v).end()
#define REV_WHOLE(v) (v).rbegin(), (v).rend()
using i64 = int64_t;
using namespace std;
template<size_t I,class H,class...T>struct TupleReaderWriter{static tuple<H,T...> r(istream&i){H v;i>>v;return tuple_cat(tuple<H>(v),TupleReaderWriter<sizeof...(T)-1,T...>::r(i));}static void w(ostream&o,tuple<H,T...>&t,string d){TupleReaderWriter<I-1,H,T...>::w(o,t,d);o<<d<<get<I>(t);}};
template<class H,class...T>struct TupleReaderWriter<0,H,T...>{static tuple<H,T...> r(istream&i){H v;i>>v;return tuple<H>(v);}static void w(ostream&o,tuple<H,T...>&t,string d){o<<get<0>(t);}};
template<class...T>istream&operator>>(istream&i,tuple<T...>&t){t=TupleReaderWriter<sizeof...(T),T...>::r(i);return i;}
template<class...T>ostream&operator<<(ostream&o,tuple<T...>&t){string delim=" ";TupleReaderWriter<sizeof...(T)-1,T...>::w(o,t,delim);return o;}
template<class T>istream&operator>>(istream&i,vector<T>&v){for(auto&x:v)i>>x;return i;}
template<class T>ostream&operator<<(ostream&o,vector<T>&v){string delim="";for(auto&x:v)o<<delim<<x,delim=" ";return o;}
template<class T>using rev_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<class T>using vector2d=vector<vector<T>>;
struct fixprec{int x;fixprec(int d):x(d){}};
ostream&operator<<(ostream&o,fixprec f){return o<<fixed<<setprecision(f.x);}
void R_YESNO(bool p) { cout << (p ? "YES" : "NO") << endl; }
void R_YesNo(bool p) { cout << (p ? "Yes" : "No") << endl; }

vector<set<int>> edge;
set<int> s_uv;

int64_t divceil(int64_t a, int64_t b) {
    return a / b + (a > 0 && a % b ? 1 : 0);
}

bool recursive(int x, int u) {
    if(x == u) return true;
    for(int y : edge[x]) {
        if(recursive(y, u)) {
            s_uv.insert(y);
            return true;
        }
    }
    return false;
}

int main() {
    int N, u, v;
    cin >> N >> u >> v;
    u--, v--;
    edge = vector<set<int>>(N);
    for(int i = 0; i < N - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        edge[a].insert(b);
        edge[b].insert(a);
    }
    // v根の木をつくる
    // 今, 前, 今の深さ
    queue<tuple<int, int, int>> q;
    vector<int> depth(N, 0), part_depth(N, 0);
    q.push(make_tuple(v, -1, 0));
    while(q.size()) {
        int cur, prev, d;
        tie(cur, prev, d) = q.front(); q.pop();
        depth[cur] = d;
        if(prev >= 0) edge[cur].erase(prev);
        for(int nxt : edge[cur]) {
            q.push(make_tuple(nxt, cur, d + 1));
        }
    }
    // u - v 間頂点探す
    {
        vector<bool> used(N, false);
        stack<pair<int, int>> st, tmp;
        st.push({v, -1});
        while(st.size()) {
            int cur, prev;
            tie(cur, prev) = st.top();
            if(used[cur]) {
                st.pop();
                if(prev >= 0)
                    part_depth[prev] = max(part_depth[prev], part_depth[cur] + 1);
                continue;
            }
            for(int nxt : edge[cur]) {
                st.push({nxt, cur});
            }
            used[cur] = true;
        }
    }

    recursive(v, u);
    s_uv.insert(v);

    int ans = 0;
    int D = depth[u] - depth[v];

    for(int w : s_uv) {
        if(u == w) continue;
        int d_u = depth[u] - depth[w];
        int d_v = depth[w] - depth[v];
        int d = part_depth[w];
        int cand = 0;
        if(d_u >= d_v) cand = (d_u + d_v) / 2;
        else {
            cand = d_v + d - 1;
        }
        ans = max(ans, cand);
    }
    cout << ans << endl;
    return 0;    
}



Measured memory_bytes: 17124