Problem:
Score : 1400 points

Problem Statement

Sigma and Sugim are playing a game.

The game is played on a graph with N vertices numbered 1 through N. The graph has N-1 red edges and N-1 blue edges, and the N-1 edges in each color forms a tree. The red edges are represented by pairs of integers (a_i, b_i), and the blue edges are represented by pairs of integers (c_i, d_i).

Each player has his own piece. Initially, Sigma's piece is at vertex X, and Sugim's piece is at vertex Y.

The game is played in turns, where turns are numbered starting from turn 1. Sigma takes turns 1, 3, 5, ..., and Sugim takes turns 2, 4, 6, ....

In each turn, the current player either moves his piece, or does nothing. Here, Sigma can only move his piece to a vertex that is directly connected to the current vertex by a red edge. Similarly, Sugim can only move his piece to a vertex that is directly connected to the current vertex by a blue edge.

When the two pieces come to the same vertex, the game ends immediately. If the game ends just after the operation in turn i, let i be the total number of turns in the game.

Sigma's objective is to make the total number of turns as large as possible, while Sugim's objective is to make it as small as possible.

Determine whether the game will end in a finite number of turns, assuming both players plays optimally to achieve their respective objectives. If the answer is positive, find the number of turns in the game.

Constraints

2 ≦ N ≦ 200,000

1 ≦ X, Y ≦ N

X \neq Y

1 ≦ a_i, b_i, c_i, d_i ≦ N

The N-1 edges in each color (red and blue) forms a tree.

Input

The input is given from Standard Input in the following format:

N X Y
a_1 b_1
a_2 b_2
:
a_{N-1} b_{N-1}
c_1 d_1
c_2 d_2
:
c_{N-1} d_{N-1}

Output

If the game will end in a finite number of turns, print the number of turns.
Otherwise, print -1.

Sample Input 1

4 1 2
1 2
1 3
1 4
2 1
2 3
1 4

Sample Output 1

4

Sample Input 2

3 3 1
1 2
2 3
1 2
2 3

Sample Output 2

4

Sample Input 3

4 1 2
1 2
3 4
2 4
1 2
3 4
1 3

Sample Output 3

2

Sample Input 4

4 2 1
1 2
3 4
2 4
1 2
3 4
1 3

Sample Output 4

-1

Sample Input 5

5 1 2
1 2
1 3
1 4
4 5
2 1
1 3
1 5
5 4

Sample Output 5

6

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Diagnostics;
using Enu = System.Linq.Enumerable;

public class Program
{
    public void Solve()
    {
        int N = NextInt(), A = NextInt() - 1, B = NextInt() - 1;
        var E = new List<int>[2][];

        for (int who = 0; who < 2; who++)
        {
            E[who] = new List<int>[N];
            for (int i = 0; i < N; i++)
                E[who][i] = new List<int>();
            for (int i = 0; i < N - 1; i++)
            {
                int a = NextInt() - 1, b = NextInt() - 1;
                E[who][a].Add(b);
                E[who][b].Add(a);
            }
        }
        var lca = new LowestCommonAncestor(B, E[1]);
        var seen = new bool[N];
        var que = new Queue<int>();
        que.Enqueue(A);
        int ans = lca.Depth(A) * 2;

        for (int steps = 1; que.Count > 0; steps++)
        {
            var nextQue = new Queue<int>();
            while (que.Count > 0)
            {
                int at = que.Dequeue();
                foreach (int next in E[0][at])
                    if (!seen[next])
                    {
                        if (lca.Dist(at, next) > 2) { Console.WriteLine(-1); return; }
                        seen[next] = true;
                        int nextDepth = lca.Depth(next);
                        if (nextDepth >= steps) ans = Math.Max(ans, nextDepth * 2);
                        if (nextDepth > steps) nextQue.Enqueue(next);
                    }
            }
            que = nextQue;
        }

        Console.WriteLine(ans);
    }

    TextReader _reader = Console.In;
    int NextInt()
    {
        int c;
        while ((c = _reader.Read()) < '0' || c > '9') { }
        int res = c - '0';
        while ((c = _reader.Read()) >= '0' && c <= '9') res = res * 10 + c - '0';
        return res;
    }

    class LowestCommonAncestor
    {
        List<int>[] G;
        RangeMinQueryIndex Rmq;
        List<int> Vs = new List<int>();
        List<int> depth = new List<int>();
        int[] Id, depthAt;

        public LowestCommonAncestor(int root, List<int>[] G)
        {
            this.G = G;
            Init(root);
        }
        public int Get(int a, int b)
        {
            int L = Math.Min(Id[a], Id[b]);
            int R = Math.Max(Id[a], Id[b]) + 1;
            int i = Rmq.Get(L, R);
            return Vs[i];
        }
        public int Depth(int a) { return depthAt[a]; }
        public int Dist(int a, int b)
        {
            return depthAt[a] + depthAt[b] - depthAt[Get(a, b)] * 2;
        }

        void Init(int root)
        {
            Id = new int[G.Length];
            depthAt = new int[G.Length];
            DFS(root, -1, 0);
            Rmq = new RangeMinQueryIndex(depth.Count);
            for (int i = 0; i < depth.Count; i++)
                Rmq.Set(i, depth[i]);
        }
        void DFS(int v, int prev, int d)
        {
            Id[v] = Vs.Count;
            Vs.Add(v);
            depth.Add(d);
            depthAt[v] = d;
            foreach (int next in G[v])
                if (next != prev)
                {
                    DFS(next, v, d + 1);
                    Vs.Add(v);
                    depth.Add(d);
                }
        }
    }

    class RangeMinQueryIndex
    {
        private static readonly int INF = (int)1e9;
        public readonly int N;
        private readonly int[] tree;
        private readonly int[] index;

        public RangeMinQueryIndex(int N)
        {
            while (N < 2 || (N & (N - 1)) != 0) { N += N & -N; }
            this.N = N;
            tree = new int[N * 2];
            index = new int[N * 2];
            for (int i = 0; i < tree.Length; i++) tree[i] = INF;
        }
        public void Set(int i, int val)
        {
            int id = i;
            i += N - 1;
            tree[i] = val;
            index[i] = id;
            while (i > 0)
            {
                i = (i - 1) / 2;
                int L = i * 2 + 1, R = i * 2 + 2;
                if (tree[L] <= tree[R]) { tree[i] = tree[L]; index[i] = index[L]; }
                else { tree[i] = tree[R]; index[i] = index[R]; }
            }
        }
        // [L, R)
        public int Get(int L, int R) { int v = -1; return Rec(0, ref v, 0, N, L, R); }
        private int Rec(int i, ref int val, int currL, int currR, int L, int R)
        {
            if (currL >= R || currR <= L) { val = INF; return -1; }
            if (currL >= L && currR <= R) { val = tree[i]; return index[i]; }
            int mid = (currL + currR) / 2;
            int Lv = INF, Rv = INF;
            int Li = Rec(i * 2 + 1, ref Lv, currL, mid, L, R);
            int Ri = Rec(i * 2 + 2, ref Rv, mid, currR, L, R);
            if (Lv <= Rv) { val = Lv; return Li; }
            val = Rv; return Ri;
        }
    }

}


class Entry { static void Main() { new Program().Solve(); } }
class Reader
{
    static TextReader reader = Console.In;
    static readonly char[] separator = { ' ' };
    static readonly StringSplitOptions op = StringSplitOptions.RemoveEmptyEntries;
    static string[] A = new string[0];
    static int i;
    static void Init() { A = new string[0]; }
    public static void Set(TextReader r) { reader = r; Init(); }
    public static void Set(string file) { reader = new StreamReader(file); Init(); }
    public static bool HasNext() { return CheckNext(); }
    public static string String() { return Next(); }
    public static int Int() { return int.Parse(Next()); }
    public static long Long() { return long.Parse(Next()); }
    public static double Double() { return double.Parse(Next()); }
    public static int[] IntLine() { return Array.ConvertAll(Split(Line()), int.Parse); }
    public static int[] IntArray(int N) { return Range(N, Int); }
    public static int[][] IntTable(int H) { return Range(H, IntLine); }
    public static string[] StringArray(int N) { return Range(N, Next); }
    public static string[][] StringTable(int N) { return Range(N, () => Split(Line())); }
    public static string Line() { return reader.ReadLine().Trim(); }
    static string[] Split(string s) { return s.Split(separator, op); }
    static T[] Range<T>(int N, Func<T> f) { var r = new T[N]; for (int i = 0; i < N; r[i++] = f()) ; return r; }
    static string Next() { CheckNext(); return A[i++]; }
    static bool CheckNext()
    {
        if (i < A.Length) return true;
        string line = reader.ReadLine();
        if (line == null) return false;
        if (line == "") return CheckNext();
        A = Split(line);
        i = 0;
        return true;
    }
}