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 Java8 (OpenJDK 1.8.0) (judge verdict: Accepted)

// package agc.agc005;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class Main {
    private static final int INF = 100000000;

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = in.nextInt();
        int A = in.nextInt()-1;
        int B = in.nextInt()-1;
        graphA = buildGraph(in, n, n-1);
        graphB = buildGraph(in, n, n-1);
        distFromA = bfs(graphA, A);
        distFromB = bfs(graphB, B);
        visited = new boolean[n];

        LCA lca = new LCA(graphB);
        canWin = new boolean[n];
        for (int i = 0; i < n ; i++) {
            if (canWin[i]) {
                continue;
            }
            for (int j : graphA[i]) {
                if (lca.dist(i, j) >= 3) {
                    canWin[i] = true;
                    canWin[j] = true;
                    break;
                }
            }
        }

        dfs(A);

        out.println(best >= INF ? -1 : best);
        out.flush();
    }

    static int best = 0;
    static boolean[] canWin;
    static boolean[] visited;

    static void dfs(int now) {
        if (canWin[now]) {
            best = INF;
        }
        visited[now] = true;
        best = Math.max(best, distFromB[now] * 2);
        for (int to : graphA[now]) {
            if (!visited[to] && distFromA[to] < distFromB[to]) {
                dfs(to);
            }
        }
    }

    public static class LCA {
        int[][] graph;
        int[][] parent;
        int[] depth;

        public LCA(int[][] graph) {
            int n = graph.length;
            this.graph = graph;
            init(n);
        }

        void dfs(int now, int from, int dep) {
            parent[0][now] = from;
            depth[now] = dep;
            for (int to : graph[now]) {
                if (to != from) {
                    dfs(to, now, dep+1);
                }
            }
        }

        void init(int n) {
            int log = 1;
            int nn = n;
            while (nn >= 1) {
                nn /= 2;
                log++;
            }
            parent = new int[log+1][n];
            for (int i = 0 ; i <= log ; i++) {
                Arrays.fill(parent[i], -1);
            }
            depth = new int[n];

            dfs(0, -1, 0);

            for (int k = 0 ; k < log ; k++) {
                for (int v = 0 ; v < n ; v++) {
                    if (parent[k][v] < 0) {
                        parent[k+1][v] = -1;
                    } else {
                        parent[k+1][v] = parent[k][parent[k][v]];
                    }
                }
            }
        }

        int lca(int u, int v) {
            int loglen = parent.length;
            if (depth[u] > depth[v]) {
                int tmp = u;
                u = v;
                v = tmp;
            }
            for (int k = 0 ; k < loglen ; k++) {
                if (((depth[v] - depth[u]) >> k) % 2 == 1) {
                    v = parent[k][v];
                }
            }
            if (u == v) {
                return u;
            }

            for (int k = loglen-1 ; k >= 0 ; k--) {
                if (parent[k][u] != parent[k][v]) {
                    u = parent[k][u];
                    v = parent[k][v];
                }
            }
            return parent[0][u];
        }

        int dist(int x, int y) {
            int l = lca(x, y);
            return depth[x] + depth[y] - depth[l] * 2;
        }
    }

    static int[] bfs(int[][] graph, int s) {
        int n = graph.length;
        int[] que = new int[n];
        int[] d = new int[n];
        Arrays.fill(d, INF);


        int qh = 0;
        int qt = 0;
        que[qh++] = s;
        d[s] = 0;
        while (qt < qh) {
            int now = que[qt++];
            int tt = d[now]+1;
            for (int to : graph[now]) {
                if (d[to] > tt) {
                    d[to] = tt;
                    que[qh++] = to;
                }
            }
        }
        return d;
    }

    static int[] distFromA;
    static int[] distFromB;

    static int[][] graphA;
    static int[][] graphB;

    static int[][] buildGraph(InputReader in, int n, int m) {
        int[][] edges = new int[m][];
        int[][] graph = new int[n][];
        int[] deg = new int[n];
        for (int i = 0 ; i < m ; i++) {
            int a = in.nextInt()-1;
            int b = in.nextInt()-1;
            deg[a]++;
            deg[b]++;
            edges[i] = new int[]{a, b};
        }
        for (int i = 0 ; i < n ; i++) {
            graph[i] = new int[deg[i]];
        }
        for (int i = 0 ; i < m ; i++) {
            int a = edges[i][0];
            int b = edges[i][1];
            graph[a][--deg[a]] = b;
            graph[b][--deg[b]] = a;
        }
        return graph;
    }

    public static void debug(Object... o) {
        System.err.println(Arrays.deepToString(o));
    }

    public static class InputReader {
        private static final int BUFFER_LENGTH = 1 << 12;
        private InputStream stream;
        private byte[] buf = new byte[BUFFER_LENGTH];
        private int curChar;
        private int numChars;

        public InputReader(InputStream stream) {
            this.stream = stream;
        }

        private int next() {
            if (numChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= numChars) {
                curChar = 0;
                try {
                    numChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (numChars <= 0)
                    return -1;
            }
            return buf[curChar++];
        }

        public char nextChar() {
            return (char) skipWhileSpace();
        }

        public String nextToken() {
            int c = skipWhileSpace();
            StringBuilder res = new StringBuilder();
            do {
                res.append((char) c);
                c = next();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        public int nextInt() {
            return (int) nextLong();
        }

        public long nextLong() {
            int c = skipWhileSpace();
            long sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = next();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = next();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public double nextDouble() {
            return Double.valueOf(nextToken());
        }

        int skipWhileSpace() {
            int c = next();
            while (isSpaceChar(c)) {
                c = next();
            }
            return c;
        }

        boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }
    }
}