/*
 　　　　　／＞　 フ
 　　　　　| 　_　 _|
 　 　　　／`ミ _x 彡
 　　 　 /　　　 　 |
 　　　 /　  ヽ　　 ?
 　／￣|　　 |　|　|
 　| (￣ヽ＿_ヽ_)_)
 　＼二つ
  */

#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MP make_pair
#define ll long long
#define fi first
#define se second
using namespace std;

template <typename T>
void read(T &x) {
    x = 0; bool f = 0;
    char c = getchar();
    for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
    for (;isdigit(c);c=getchar()) x=x*10+(c^48);
    if (f) x=-x;
}

template<typename F>
inline void write(F x, char ed = '\n') {
    static short st[30];short tp=0;
    if(x<0) putchar('-'),x=-x;
    do st[++tp]=x%10,x/=10; while(x);
    while(tp) putchar('0'|st[tp--]);
    putchar(ed);
}

template <typename T>
inline void Mx(T &x, T y) { x < y && (x = y); }

template <typename T>
inline void Mn(T &x, T y) { x > y && (x = y); }

/***********************
 *
 * SegmentTree
 *
***********************/

const int N = 200500;
#define ls p << 1
#define rs ls | 1
int X[N], Y[N];
int tag[N<<2], mn[N<<2], add[N<<2];
void Tag(int p, int x, int d) {
    tag[p] ^= x, add[p] += d, mn[p] += d;
}

void spread(int p) {
    if (add[p] || tag[p]) Tag(ls, tag[p], add[p]), Tag(rs, tag[p], add[p]);
    add[p] = tag[p] = 0;
}

void change(int p, int l, int r, int L, int R, int x, int d) {
    if (L <= l && r <= R) return Tag(p, x, d);
    int mid = (l + r) >> 1; spread(p);
    if (L <= mid) change(ls, l, mid, L, R, x, d);
    if (mid < R) change(rs, mid + 1, r, L, R, x, d);
    mn[p] = min(mn[ls], mn[rs]);
}

int query(int p, int l, int r) {
    if (l == r) return mn[p] = 0x3f3f3f3f, tag[p];
    int mid = (l + r) >> 1, t; spread(p);
    if (mn[ls] == 1) t = query(ls, l, mid);
    else t = query(rs, mid + 1, r);
    mn[p] = min(mn[ls], mn[rs]);
    return t;
}

/*********************
 *
 * TreeDivideAndConquer
 *
*********************/

int h[N], ne[N<<1], to[N<<1], tot, n;
inline void adde(int x, int y) { ne[++tot] = h[x], to[h[x] = tot] = y; }
int dep[N], siz[N], son[N], Top[N], f[N], dfn[N], num;
void dfs1(int x, int fa) {
    dep[x] = dep[f[x] = fa] + (siz[x] = 1);
    for (int i = h[x]; i; i = ne[i]) {
        int y = to[i]; if (y == fa) continue;
        dfs1(y, x), siz[x] += siz[y];
        if (siz[y] > siz[son[x]]) son[x] = y;
    }
}

void dfs2(int x, int topf) {
    dfn[x] = ++num, Top[x] = topf; if (son[x]) dfs2(son[x], topf);
    for (int i = h[x], y; i; i = ne[i])
        if ((y = to[i]) != f[x] && y != son[x]) dfs2(y, y);
}

void change(int x, int y, int num, int d) {
    while (Top[x] != Top[y]) {
        if (dep[Top[x]] < dep[Top[y]]) swap(x, y);
        change(1, 2, n, dfn[Top[x]], dfn[x], num, d);
        x = f[Top[x]];
    }
    if (dep[x] < dep[y]) swap(x, y);
    if (x != y) change(1, 2, n, dfn[y] + 1, dfn[x], num, d);
}

int main() {
    read(n);
    for (int i = 1, x, y;i < n; i++)
        read(x), read(y), adde(x, y), adde(y, x);
    dfs1(1, 0), dfs2(1, 1);
    /* for (int i = 1;i <= n; i++) write(siz[i], ' '), write(Top[i], ' '), write(dfn[i]); */
    for (int i = 1;i < n; i++) 
        read(X[i]), read(Y[i]), change(X[i], Y[i], i, 1);

    for (int i = 1;i < n; i++) {
        /* write(mn[1]); */
        if (mn[1] != 1) return puts("NO"), 0;
        int t = query(1, 2, n);
        change(X[t], Y[t], t, -1);
    }
    puts("YES");
    return 0;
}

Measured memory_bytes: 15400