Problem:
Score : 1400 points

Problem Statement

There is a tree with N vertices numbered 1 through N.
The i-th of the N-1 edges connects vertices a_i and b_i.

Initially, each edge is painted blue.
Takahashi will convert this blue tree into a red tree, by performing the following operation N-1 times:

Select a simple path that consists of only blue edges, and remove one of those edges.

Then, span a new red edge between the two endpoints of the selected path.

His objective is to obtain a tree that has a red edge connecting vertices c_i and d_i, for each i.

Determine whether this is achievable.

Constraints

2 ≤ N ≤ 10^5

1 ≤ a_i,b_i,c_i,d_i ≤ N

a_i ≠ b_i

c_i ≠ d_i

Both input graphs are trees.

Input

Input is given from Standard Input in the following format:

N
a_1 b_1
:
a_{N-1} b_{N-1}
c_1 d_1
:
c_{N-1} d_{N-1}

Output

Print YES if the objective is achievable; print NO otherwise.

Sample Input 1

3
1 2
2 3
1 3
3 2

Sample Output 1

YES

The objective is achievable, as below:

First, select the path connecting vertices 1 and 3, and remove a blue edge 1-2. Then, span a new red edge 1-3.

Next, select the path connecting vertices 2 and 3, and remove a blue edge 2-3. Then, span a new red edge 2-3.

Sample Input 2

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

Sample Output 2

YES

Sample Input 3

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

Sample Output 3

NO

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Globalization;
using System.Diagnostics;



class Myon
{
    public Myon() { }
    public static int Main()
    {
        new Myon().calc();
        return 0;
    }

    Scanner cin;

    int N, M;
    int[] a, b, c, d;
    List<int>[] es;
    List<int>[] es2;
    List<int>[] conne;

    void calc()
    {
        cin = new Scanner();
        N = cin.nextInt();
        M = N - 1;
        a = new int[M];
        b = new int[M];
        Dictionary<long, int> dic = new Dictionary<long, int>();
        for (int i = 0; i < M; i++)
        {
            a[i] = cin.nextInt() - 1;
            b[i] = cin.nextInt() - 1;
            if (a[i] > b[i]) swap(ref a[i], ref b[i]);
            dic[getHash(a[i], b[i])] = i;
        }
        

        List<int> fa = new List<int>();
        List<int> fc = new List<int>();
        Dictionary<int, int> da = new Dictionary<int, int>();
        Dictionary<int, int> dc = new Dictionary<int, int>();

        c = new int[M];
        d = new int[M];
        for (int i = 0; i < M; i++)
        {
            c[i] = cin.nextInt() - 1;
            d[i] = cin.nextInt() - 1;
            if (c[i] > d[i]) swap(ref c[i], ref d[i]);
            long hash = getHash(c[i], d[i]);
            if(dic.ContainsKey(hash))
            {
                fc.Add(i);
                fa.Add(dic[hash]);
                da[dic[hash]] = i;
                dc[i] = dic[hash];
            }
        }
        
        state = new int[N];
        Estate = new int[M];

        es = new List<int>[N];
        es2 = new List<int>[N];
        conne = new List<int>[N];
        for (int i = 0; i < N; i++)
        {
            es[i] = new List<int>();
            es2[i] = new List<int>();
            conne[i] = new List<int>();
        }


        for (int i = 0; i < M; i++)
        {
            if (da.ContainsKey(i)) continue;
            es[a[i]].Add(i);
            es[b[i]].Add(i);
        }
        for (int i = 0; i < M; i++)
        {
            if (dc.ContainsKey(i)) continue;
            es2[c[i]].Add(i);
            es2[d[i]].Add(i);
        }

        if (fa.Count == 0)
        {
            Console.WriteLine("NO");
            return;
        }

        addQ = new Queue<int>();
        bool first = true;

        int memo = -1;
        foreach (var item in fa)
        {
            if (first)
            {
                memo = item;
                first = false;
            }
            else
            {
                Estate[da[item]] = 4;
                conne[a[item]].Add(b[item]);
                conne[b[item]].Add(a[item]);
            }
        }

        update(a[memo]);
        update(a[memo]);
        update(b[memo]);
        update(b[memo]);
        Estate[da[memo]] = 4;


        while (addQ.Count > 0)
        {
            int now = addQ.Dequeue();
            if (state[c[now]] == 1) update(c[now]);
            if (state[d[now]] == 1) update(d[now]);
        }

        for (int i = 0; i < N; i++)
        {
            //Console.WriteLine(state[i]);
        }

        for (int i = 0; i < M; i++)
        {
            if(Estate[i] != 4)
            {
                Console.WriteLine("NO");
                return;
            }
        }
        Console.WriteLine("YES");

    }

    int[] state;
    int[] Estate;
    Queue<int> addQ;
    
    void update(int now)
    {
        state[now]++;

        foreach (var item in conne[now])
        {
            if (state[item] < state[now])
            {
                update(item);
            }
        }

        foreach (var item in es2[now])
        {
            Estate[item]++;
            if(Estate[item] == 3)
            {
                addQ.Enqueue(item);
            }
        }

        if (state[now] == 2)
        {
            foreach (var item in es[now])
            {
                int next = a[item] + b[item] - now;
                if(state[next] == 0) update(next);
            }
        }


    }


    //swap
    void swap<T>(ref T a, ref T b)
    {
        T c = a;
        a = b;
        b = c;
    }


    long getHash(long a, long b)
    {
        long hash = 0;
        hash += a * 19786316311312L;
        hash += b * 535871674169487L;
        return hash;
    }
}

class Scanner
{
    string[] s;
    int i;

    char[] cs = new char[] { ' ' };

    public Scanner()
    {
        s = new string[0];
        i = 0;
    }

    public string next()
    {
        if (i < s.Length) return s[i++];
        string st = Console.ReadLine();
        while (st == "") st = Console.ReadLine();
        s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
        i = 0;
        return s[i++];
    }

    public int nextInt()
    {
        return int.Parse(next());
    }

    public long nextLong()
    {
        return long.Parse(next());
    }

    public double nextDouble()
    {
        return double.Parse(next());
    }

}