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# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Linq;
using System.Numerics;
using System.Collections.Generic;
using System.IO;
using System.Text;
using N = System.Int32;

public class Solver
{
    public void Solve()
    {
        N n = ri;
        N u = ri - 1;
        N v = ri - 1;
        List<List<N>> path = new List<List<N>>();
        for (int i = 0; i < n; i++)
        {
            path.Add(new List<N>());
        }
        N a = 0;
        N b = 0;
        for (int i = 0; i < n - 1; i++)
        {
            a = ri - 1;
            b = ri - 1;
            path[a].Add(b);
            path[b].Add(a);
        }
        N[] dis_t = new N[n];
        N[] dis_a = new N[n];
        bool[] stack = new bool[n];
        bool[] seen = new bool[n];
        seen[u] = true;
        stack[u] = true;
        while (stack.Any(x => x == true))
        {
            for (int i = 0; i < n; i++)
            {
                if (!stack[i]) continue;
                stack[i] = false;
                foreach (var to in path[i])
                {
                    if (!seen[to])
                    {
                        dis_t[to] = dis_t[i] + 1;
                        seen[to] = true;
                        stack[to] = true;
                    }
                }
            }
        }
        seen = new bool[n];
        seen[v] = true;
        stack[v] = true;
        while (stack.Any(x => x == true))
        {
            for (int i = 0; i < n; i++)
            {
                if (!stack[i]) continue;
                stack[i] = false;
                foreach (var to in path[i])
                {
                    if (!seen[to])
                    {
                        dis_a[to] = dis_a[i] + 1;
                        seen[to] = true;
                        stack[to] = true;
                    }
                }
            }
        }
        N p = 0;
        for(int i = 0; i < n; i++)
        {
            if (dis_a[i] > dis_t[i] && p < dis_a[i]) p = dis_a[i];
        }
        Write(p - 1);
    }




    int ri { get { return sc.Integer(); } }
    long rl { get { return sc.Long(); } }
    double rd { get { return sc.Double(); } }
    string rs { get { return sc.Scan(); } }
    public StreamScanner sc = new StreamScanner(Console.OpenStandardInput());
    public Algorithm alg = new Algorithm();

    /*
    private const N mod = 1000000007;
    N Reverse(N n) { return Pow(n, mod - 2); }
    N Mul(params N[] n) { N p = n[0]; for (N i = 1; i < n.Length; i++) { p = (p * n[i]) % mod; } return p; }
    N Pow(N n, N p) { N t = n, q = 1; while (p > 0) { if (p % 2 == 1) { q = (q * t) % mod; } t = (t * t) % mod; p >>= 1; } return q; }
    N PowUpper(N n, N b) { N p = 1; while (p <= n) { p *= b; } return p; }
    N Sign(N n) { return n == 0 ? 0 : n > 0 ? 1 : -1; }
    N Abs(N n) { return (n > 0) ? n : -n; }
    N Gcd(params N[] n) { N p = n[0]; for (N i = 1; i < n.Length; i++) { p = Gcd(p, n[i]); } return p; }
    N Gcd(N a, N b) { return (a == 0) ? b : Gcd(b % a, a); }
    N Lcm(params N[] n) { N p = n[0]; for (N i = 1; i < n.Length; i++) { p = Lcm(p, n[i]); } return p; }
    N Lcm(N a, N b) { return (a / Gcd(a, b) * b) % mod; }
    */
    void Write<T>(T t) { Console.WriteLine(t.ToString()); }
    void YN(bool t) { Console.WriteLine(t ? "YES" : "NO"); }
    void Yn(bool t) { Console.WriteLine(t ? "Yes" : "No"); }
    void yn(bool t) { Console.WriteLine(t ? "yes" : "no"); }
}

static class Program
{
    static public void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        var solver = new Solver();
        solver.Solve();
        Console.Out.Flush();
    }
}

public class Algorithm
{
    public int[] ZAlgorithm(string s)
    {
        int[] p = new int[s.Length];
        p[0] = s.Length;
        int i = 1, j = 0;
        while (i < s.Length)
        {
            while (i + j < s.Length && s[j] == s[i + j]) ++j;
            p[i] = j;
            if (j == 0) { ++i; continue; }
            int k = 1;
            while (i + k < s.Length && k + p[k] < j)
            {
                p[i + k] = p[k];
                ++k;
            }
            i += k; j -= k;
        }
        return p;
    }

    public List<int> SieveOfEratosthenes(int n)
    {
        List<int> l = new List<int>();
        if (n >= 2) { l.Add(2); }
        bool[] t = new bool[(n - 1) / 2];
        for (int p = 3; p <= n; p += 2) { if (!t[(p - 3) / 2]) { l.Add(p); for (int q = p * p; q <= n; q += p) { t[(q - 3) / 2] = true; } } }
        return l;
    }

    public Dictionary<int,int> PrimeFactor(int n, List<int> primetable)
    {
        Dictionary<int, int> d = new Dictionary<int, int>();
        int t = 0;
        foreach(int i in primetable)
        {
            if (n % i == 0)
            {
                while (n % 2 == 0) { n /= i; t++; }
                d.Add(i, t);
            }
        }
        if (n > 1) { d.Add(n, 1); }
        return d;
    }
}

public class PriorityQueue<T> where T : IComparable
{
    private IComparer<T> _comparer = null;
    private int _type = 0;

    private T[] _heap;
    private int _sz = 0;

    private int _count = 0;

    /// <summary>
    /// Priority Queue with custom comparer
    /// </summary>
    public PriorityQueue(IComparer<T> comparer)
    {
        _heap = new T[128];
        _comparer = comparer;
    }

    /// <summary>
    /// Priority queue
    /// </summary>
    /// <param name="type">0: asc, 1:desc</param>
    public PriorityQueue(int type = 0)
    {
        _heap = new T[128];
        _type = type;
    }

    private int Compare(T x, T y)
    {
        if (_comparer != null) return _comparer.Compare(x, y);
        return _type == 0 ? x.CompareTo(y) : y.CompareTo(x);
    }

    public void Push(T x)
    {
        _count++;
        if (_count > _heap.Length)
        {
            var newheap = new T[_heap.Length * 2];
            for (int n = 0; n < _heap.Length; n++) newheap[n] = _heap[n];
            _heap = newheap;
        }

        //node number
        var i = _sz++;

        while (i > 0)
        {
            //parent node number
            var p = (i - 1) / 2;

            if (Compare(_heap[p], x) <= 0) break;

            _heap[i] = _heap[p];
            i = p;
        }

        _heap[i] = x;
    }

    public T Pop()
    {
        _count--;

        T ret = _heap[0];
        T x = _heap[--_sz];

        int i = 0;
        while (i * 2 + 1 < _sz)
        {
            //children
            int a = i * 2 + 1;
            int b = i * 2 + 2;

            if (b < _sz && Compare(_heap[b], _heap[a]) < 0) a = b;

            if (Compare(_heap[a], x) >= 0) break;

            _heap[i] = _heap[a];
            i = a;
        }

        _heap[i] = x;

        return ret;
    }

    public int Count()
    {
        return _count;
    }

    public T Peek()
    {
        return _heap[0];
    }

    public bool Contains(T x)
    {
        for (int i = 0; i < _sz; i++) if (x.Equals(_heap[i])) return true;
        return false;
    }

    public void Clear()
    {
        while (this.Count() > 0) this.Pop();
    }

    public IEnumerator<T> GetEnumerator()
    {
        var ret = new List<T>();

        while (this.Count() > 0)
        {
            ret.Add(this.Pop());
        }

        foreach (var r in ret)
        {
            this.Push(r);
            yield return r;
        }
    }

    public T[] ToArray()
    {
        T[] array = new T[_sz];
        int i = 0;

        foreach (var r in this)
        {
            array[i++] = r;
        }

        return array;
    }
}

public class StreamScanner
{
    public StreamScanner(Stream stream) { str = stream; }
    private readonly Stream str;
    private readonly byte[] buf = new byte[1024];
    private int len, ptr;
    public bool isEof = false;
    public bool IsEndOfStream { get { return isEof; } }
    private byte read()
    {
        if (isEof) throw new EndOfStreamException();
        if (ptr >= len)
        {
            ptr = 0;
            if ((len = str.Read(buf, 0, 1024)) <= 0)
            {
                isEof = true;
                return 0;
            }
        }
        return buf[ptr++];
    }
    public char Char()
    {
        byte b = 0;
        do b = read();
        while (b < 33 || 126 < b);
        return (char)b;
    }
    public string Scan()
    {
        var sb = new StringBuilder();
        for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
            sb.Append(b);
        return sb.ToString();
    }
    public long Long()
    {
        long ret = 0; byte b = 0; var ng = false;
        do b = read();
        while (b != '-' && (b < '0' || '9' < b));
        if (b == '-') { ng = true; b = read(); }
        for (; true; b = read())
        {
            if (b < '0' || '9' < b)
                return ng ? -ret : ret;
            else ret = ret * 10 + b - '0';
        }
    }
    public int Integer() { return (int)Long(); }
    public double Double() { return double.Parse(Scan()); }
}