#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define N 101000
#define NN 401000
template<typename T> inline void read(T &x) {
  x = 0; char c = getchar();
  while (!isdigit(c)) c = getchar();
  while (isdigit(c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); }
}
using namespace std;
int n;
struct edge{
  int nxt, to;
}e[N << 1];
int head[N], ecnt;
inline void addedge(int from, int to) {
  e[++ecnt] = (edge){head[from], to};
  head[from] = ecnt;
}

int son[N], siz[N], dep[N], fa[N];
void dfs_son(int cur, int faa) {
  fa[cur] = faa, siz[cur] = 1, dep[cur] = dep[faa] + 1;
  int mx = 0;
  for (int i = head[cur]; i; i = e[i].nxt) {
    int to = e[i].to; if (to == faa)  continue;
    dfs_son(to, cur); siz[cur] += siz[to];
    if (siz[to] > mx) mx = siz[to], son[cur] = to;
  }
}
int top[N], dfn[N], dcnt;
void dfs_chain(int cur, int topp) {
  top[cur] = topp, dfn[cur] = ++dcnt;
  if (son[cur]) dfs_chain(son[cur], topp);
  for (int i= head[cur]; i; i = e[i].nxt) {
    int to = e[i].to; if (to == fa[cur] || to == son[cur])  continue;
    dfs_chain(to, to);
  }
}

int U[N], V[N];
int taga[NN], tagx[NN], mn[NN], mnpos[NN];
int ls[NN], rs[NN], ttot, root;
void build(int L, int R, int &cur) {
  cur = ++ttot;
  mnpos[cur] = L;
  if (L == R) return ;
  int mid = (L + R) >> 1;
  build(L, mid, ls[cur]), build(mid + 1, R, rs[cur]);
}
inline void pushup(int cur) {
  if (mn[ls[cur]] < mn[rs[cur]])  mn[cur] = mn[ls[cur]], mnpos[cur] = mnpos[ls[cur]];
  else  mn[cur] = mn[rs[cur]], mnpos[cur] = mnpos[rs[cur]];
}
inline void pushadd(int cur, int x) {
  if (!cur) return ;
  mn[cur] += x; taga[cur] += x;
}
inline void pushxor(int cur, int x) {
  if (!cur) return ;
  tagx[cur] ^= x;
}
inline void pushdown(int cur) {
  if (taga[cur])  pushadd(ls[cur], taga[cur]), pushadd(rs[cur], taga[cur]), taga[cur] = 0;
  if (tagx[cur])  pushxor(ls[cur], tagx[cur]), pushxor(rs[cur], tagx[cur]), tagx[cur] = 0;
}
void add(int L, int R, int l, int r, int x, int cur) {
//  printf("add(%d, %d, %d, %d, %d, %d)\n", L, R, l, r, x, cur);
  if (!R) exit(0);
  if (l <= L && R <= r) {
    taga[cur] += x; mn[cur] += x; return ;
  }
  pushdown(cur);
  int mid = (L + R) >> 1;
//  printf("mid = %d\n", mid);
  if (l <= mid) add(L, mid, l, r, x, ls[cur]);
  if (r > mid)  add(mid + 1, R, l, r, x, rs[cur]);
  pushup(cur);
//  printf("addend : mn[%d] = %d\n", cur, mn[cur]);
}
void Xor(int L, int R, int l, int r, int x, int cur) {
  if (l <= L && R <= r) {
    pushxor(cur, x);
    return ;
  }
  pushdown(cur);
  int mid = (L + R) >> 1;
  if (l <= mid) Xor(L, mid, l, r, x, ls[cur]);
  if (r > mid)  Xor(mid + 1, R, l, r, x, rs[cur]);
  pushup(cur);
}
int query(int L, int R, int pos, int cur) {
  if (L == R) return tagx[cur];
  pushdown(cur);
  int mid = (L + R) >> 1;
  if (pos <= mid) return query(L, mid, pos, ls[cur]);
  return query(mid + 1, R, pos, rs[cur]);
}

inline void Add(int x, int y, int id, int type) {
  while (top[x] != top[y]) {
    if (dep[top[x]] < dep[top[y]])  swap(x, y);
    add(1, n, dfn[top[x]], dfn[x], type, root);
    Xor(1, n, dfn[top[x]], dfn[x], id, root);
    x = fa[top[x]];
  }
  if (x == y) return ;
  if (dep[x] > dep[y])  swap(x, y);
  add(1, n, dfn[x] + 1, dfn[y], type, root);
  Xor(1, n, dfn[x] + 1, dfn[y], id, root);
}

int main() {
  read(n);
  for (int i = 1; i < n; ++i) {
    int u, v; read(u), read(v);
    addedge(u, v), addedge(v, u);
  }
  dfs_son(1, 0), dfs_chain(1, 1);
  build(1, n, root);
  for (int i = 1; i < n; ++i) {
    int u, v; read(u), read(v);
    U[i] = u, V[i] = v;
    Add(u, v, i, 1);
  }
  add(1, n, 1, 1, 1000000, root);
  int ct = 0;
  while (ct < n - 1) {
    if (mn[root] != 1) {
//      printf("mn[%d] = %d\n", root, mn[root]);
      puts("NO");
      return 0;
    }
    int p = mnpos[root];
    int id = query(1, n, p, root);
    add(1, n, p, p, 1000000, root);
//    printf("  id = %d!\n", id);
    ++ct;
    Add(U[id], V[id], id, -1);
  }
  puts("YES");
  return 0;
}


Measured memory_bytes: 18416