Problem:
Score : 600 points

Problem Statement

We have a tree with N vertices. The i-th edge connects Vertex A_i and B_i bidirectionally.

Takahashi is standing at Vertex u, and Aoki is standing at Vertex v.

Now, they will play a game of tag as follows:

1. If Takahashi and Aoki are standing at the same vertex, the game ends. Otherwise, Takahashi moves to a vertex of his choice that is adjacent to his current vertex.

2. If Takahashi and Aoki are standing at the same vertex, the game ends. Otherwise, Aoki moves to a vertex of his choice that is adjacent to his current vertex.

3. Go back to step 1.

Takahashi performs his moves so that the game ends as late as possible, while Aoki performs his moves so that the game ends as early as possible.

Find the number of moves Aoki will perform before the end of the game if both Takahashi and Aoki know each other's position and strategy.

It can be proved that the game is bound to end.

Constraints

2 \leq N \leq 10^5

1 \leq u,v \leq N

u \neq v

1 \leq A_i,B_i \leq N

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

N u v
A_1 B_1
:
A_{N-1} B_{N-1}

Output

Print the number of moves Aoki will perform before the end of the game.

Sample Input 1

5 4 1
1 2
2 3
3 4
3 5

Sample Output 1

2

If both players play optimally, the game will progress as follows:

Takahashi moves to Vertex 3.

Aoki moves to Vertex 2.

Takahashi moves to Vertex 5.

Aoki moves to Vertex 3.

Takahashi moves to Vertex 3.

Here, Aoki performs two moves.

Note that, in each move, it is prohibited to stay at the current vertex.

Sample Input 2

5 4 5
1 2
1 3
1 4
1 5

Sample Output 2

1

Sample Input 3

2 1 2
1 2

Sample Output 3

0

Sample Input 4

9 6 1
1 2
2 3
3 4
4 5
5 6
4 7
7 8
8 9

Sample Output 4

5

Solution in C++14 (GCC 5.4.1) (judge verdict: Runtime Error)

#pragma GCC optimize("Ofast","unroll-loops")
#pragma comment(linker, "/stack:200000000")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
using namespace::std;
//struct __INIT{__INIT(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(15);}} __init;
__attribute__((constructor))
void init(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cout<<fixed<<setprecision(15);
}
// random_device rd;
// mt19937 mt(rd());
// #include <boost/numeric/interval.hpp>
// #include <boost/numeric/interval/io.hpp>
// #include <boost/intrusive/rbtree.hpp>
// #include <boost/dynamic_bitset.hpp>
// #include <boost/geometry.hpp>
// #include <boost/geometry/geometries/linestring.hpp>
// #include <boost/geometry/geometries/polygon.hpp>
// #include <boost/geometry/geometries/point_xy.hpp>
// #include <boost/math/tools/minima.hpp>
// using boost::math::tools::brent_find_minima;
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
namespace mp = boost::multiprecision;
typedef mp::number<mp::cpp_dec_float<0>> cdouble;
typedef mp::cpp_int cint;
// #include <boost/unordered_map.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#include<ext/pb_ds/tag_and_trait.hpp>
template<typename T=long long>using pbds=__gnu_pbds::tree<T,__gnu_pbds::null_type,less<T>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;
template<typename T=long long>using pbds_map=__gnu_pbds::tree<T,T,less<T>,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update>;
template<typename T=long long>using pqueue =__gnu_pbds::priority_queue<T, less<T>,__gnu_pbds::rc_binomial_heap_tag>;
typedef long long lint;
typedef long long ll;
typedef long double ldouble;
typedef vector<lint> vec;
typedef vector<vector<lint>> mat;
typedef vector<vector<vector<lint>>> mat3;
typedef vector<double> dvec;
typedef vector<vector<double>> dmat;
typedef vector<vector<vector<double>>> dmat3;
typedef vector<string> svec;
typedef vector<vector<string>> smat;
typedef vector<vector<vector<string>>> smat3;
template<typename T>using Vec=vector<T>;
template<typename T>using Mat=vector<vector<T>>;
template<typename T>using Mat3=vector<vector<vector<T>>>;
template<typename T>using Mat4=vector<vector<vector<vector<T>>>>;
template<typename S,typename T>using pvec=vector<pair<S,T>>;
template<typename S,typename T>using pmat=vector<vector<pair<S,T>>>;
template<typename S,typename T>using pmat3=vector<vector<vector<pair<S,T>>>>;
template<typename S,typename T>using pmat4=vector<vector<vector<vector<pair<S,T>>>>>;
template<typename... T>using tvec=vector<tuple<T...>>;
template<typename... T>using tmat=vector<vector<tuple<T...>>>;
template<typename... T>using tmat3=vector<vector<vector<tuple<T...>>>>;
template<typename... T>using tmat4=vector<vector<vector<vector<tuple<T...>>>>>;
#define rep(i, n) for(lint i = 0; i < (lint)(n); i++)
#define irep(i) for(lint i = 0;; i++)
#define irep1(i) for(lint i = 1;; i++)
#define irep2(i) for(lint i = 2;; i++)
#define rrep(i, n) for(lint i = (lint)(n-1); i >-1; i--)
#define rrepi(i,a,b) for(lint i = (lint)(b-1); i >a-1; i--)
#define repi(i,a,b) for(lint i=lint(a);i<lint(b);i++)
#define rep2(i,a,b,c) for(lint i=lint(a);i>lint(b);i+=c)
#define all(x) (x).begin(),(x).end()
#define dist(x1,y1,x2,y2) (pow(pow(x2-x1,2)+pow(y2-y1,2),0.5))
//#define input(a,n) lint n;cin>>n;vector<lint>a(n);rep(i,n)cin>>a[i];
#define SUM(v) accumulate(all(v),0LL)
#define INF (1LL<<60)
#define IINF (1<<30)
#define EPS (1e-10)
#define LINF 9223372036854775807LL
//#define MOD 998244353LL
#define MOD 1000000007LL
#define endl "\n"
template<typename T>inline void numout(T t){bool f=0;for(auto i:t){cout<<(f?" ":"")<<i<INF/2?i:"INF";f=1;}cout<<endl;}
template<typename T>inline void numout2(T t){for(auto i:t)numout(i);}
template<typename T>inline void output(T t){bool f=0;for(auto i:t){cout<<(f?" ":"")<<i;f=1;}cout<<endl;}
template<typename T>inline void output2(T t){for(auto i:t)output(i);}
template<typename T>inline void _output(T t){bool f=0;for(int i=0;i<t.size();i++){cout<<f?"":" "<<t[i];f=1;}cout<<endl;}
template<typename T>inline void _output2(T t){for(int i=0;i<t.size();i++)output(t[i]);}
auto call=[](auto f,auto... args){return f(f,args...);};
template<typename T=lint>T in(){return *istream_iterator<T>(cin);}
template<typename T=lint>inline T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<typename T=lint>inline T lcm(T a,T b){return a/gcd(a,b)*b;}
template<typename T>inline T minq(T a,T b){return min(a,b);}
template<typename T>inline T maxq(T a,T b){return max(a,b);}
inline bool chmin(auto& s,const auto& t){bool res=s>t;s=min(s,t);return res;}
inline bool chmax(auto& s,const auto& t){bool res=s<t;s=max(s,t);return res;}
const vector<lint> dx={-1,1,0,0,1,1,-1,-1};
const vector<lint> dy={0,0,-1,1,1,-1,1,-1};

vector<lint> depth(lint start,vector<vector<lint>>G){
	vector<lint>memo(G.size());
	auto f=[&](auto f,lint v,lint p)->lint{
		lint mx=0;
		for(auto t:G[v]){
			if(t==p)continue;
			mx=max(mx,f(f,t,v));
		}
		return memo[v]=mx+1;
	};
	call(f,start,-1);
	return memo;
}

template<typename Int>
class LCA{
    template<typename T>
    class sparse_table{
        using F=function<T(T,T)>;
        F f;
        vector<vector<T>>data;
        public:
        sparse_table(vector<T> v,F f):f(f){
            int n=v.size(),log=log2(n)+1;
            data.resize(n,vector<T>(log));
            for(int i=0;i<n;i++)data[i][0]=v[i];
            for(int j=1;j<log;j++)for(int i=0;i+(1<<(j-1))<n;i++){
                data[i][j]=f(data[i][j-1],data[i+(1<<(j-1))][j-1]);
            }
        }
        T get(int l,int r){
            if(r<l)swap(l,r);
            //assert(0<l||r<=(T)data.size());
            int k=log2(r-l);
            return f(data[l][k],data[r-(1<<k)][k]);
        }
    };
    vector<pair<Int,Int>> data;
    vector<Int> start;
    sparse_table<pair<Int,Int>>* st;
	vector<Int> dep;
    public:
    LCA(vector<vector<Int>> v,Int s){
        data.resize(v.size()*2-1);
        start.resize(v.size());
        Int i=0;
        dep=depth(s,v);
        auto f=[&](auto f,Int n,Int p)->void{
            start[n]=i;
            data[i++]=make_pair(dep[n],n);
            for(Int t:v[n]){
                if(t==p)continue;
                f(f,t,n);
                data[i++]=make_pair(dep[n],n);
            }
        };
        call(f,s,-1);
        st=new sparse_table<pair<Int,Int>>(data,[](auto s,auto t){return s.first>t.first?s:t;});
    }
    Int lca(auto p,auto q){
        return st->get(min(start[p],start[q]),max(start[p],start[q])+1).second;
    }
	Int distance(auto p,auto q){
        return 2*dep[lca(p,q)]-dep[p]-dep[q];
    }
    private:
    vector<Int> depth(Int start,vector<vector<Int>>G){
        vector<Int>memo(G.size());
        auto f=[&](auto f,Int v,Int p)->Int{
            Int mx=0;
            for(auto t:G[v]){
                if(t==p)continue;
                mx=max(mx,f(f,t,v));
            }
            return memo[v]=mx+1;
        };
        call(f,start,-1);
        return memo;
    }
};

int main(){
	lint n,u,v;
	cin>>n>>u>>v;
	mat g(n);
	rep(i,n-1){
		lint s,t;
		cin>>s>>t;
		s--;t--;
		g[s].push_back(t);
		g[t].push_back(s);
	}
	//output2(g);
	auto a=depth(--u,g);
	auto b=depth(--v,g);
	lint ans=0;
	LCA<lint> lca(g,0);
	rep(i,2*n){
		if(u==v){
			cout<<i<<endl;
			return 0;
		}
		lint mx=-INF,t=-1;
		if(g[u].size()==1)u=g[u][0];
		else {
			for(auto d:g[u]){
				if(lca.distance(d,v)>=2&&lca.distance(d,v)<lca.distance(u,v)){
					u=t;
					break;
				}
				if(lca.distance(d,v)>=2&&chmax(mx,b[d]))t=d;
			}
		}
		if(u==v){
			cout<<i<<endl;
			return 0;
		}
		if(g[v].size()==1)v=g[v][0];
		else {
			for(auto d:g[v]){
				if(lca.distance(u,v)>=lca.distance(u,d))t=d;
			}
			v=t;
		}
	}
	cout<<ans<<endl;
}