#pragma GCC optimize("O2,Ofast,inline,unroll-all-loops,-ffast-math")
#pragma GCC target("popcnt")
#include <bits/stdc++.h>
#define maxn 100010
#define ll long long
#define ull unsigned long long
#define ld long double
#define fi first
#define se second
#define pb push_back
#define pob pop_back
#define pf push_front
#define pof pop_front
#define pii pair<int, int>
#define pil pair<int, ll>
#define pll pair<ll, ll>
#define IL inline
#define ss system
using namespace std;

struct edge {
  int u, v;
} es[maxn];
int tag[maxn << 2], n, cnt = 0;
bool vis[maxn];
typedef int Array[maxn];
Array fa, sz, son, top, dep, dfn;
pii t[maxn << 2];
vector<int> nxt[maxn], id[maxn << 2];
template <class T> void read (T &x) {
  char ch = x = 0;
  bool fl = false;
  while (!isdigit(ch))
    fl |= ch == '-', ch = getchar();
  while (isdigit(ch))
    x = x * 10 + ch - '0', ch = getchar();
  x = fl ? -x : x;
}
void pushup(int x) {
  t[x] = min(t[x << 1], t[x << 1 | 1]);
}
void pushdown(int x) {
  if (!tag[x])
    return;
  t[x << 1].fi += tag[x], t[x << 1 | 1].fi += tag[x];
  tag[x << 1] += tag[x], tag[x << 1 | 1] += tag[x], tag[x] = 0;
}
void build(int x, int l, int r) {
  if (l == r)
    return t[x].se = l, void();
  int mid = l + r >> 1;
  build(x << 1, l, mid);
  build(x << 1 | 1, mid + 1, r);
}
void update(int x, int ql, int qr, int l, int r, int val) {
  if (ql > qr)
    return;
  if (ql <= l && r <= qr) {
    int delt = val > 0 ? id[x].pb(val), 1 : -1;
    return t[x].fi += delt, tag[x] += delt, void();
  }
  pushdown(x);
  int mid = l + r >> 1;
  if (ql <= mid)
    update(x << 1, ql, qr, l, mid, val);
  if (qr >= mid + 1)
    update(x << 1 | 1, ql, qr, mid + 1, r, val);
  pushup(x);
}
void query(int x, int pos, int l, int r, int &res) {
  while (!id[x].empty() && vis[id[x].back()]) {
    id[x].pob();
  }
  if (!id[x].empty())
    res = id[x].back();
  if (l == r)
    return t[x].fi = 1 << 30, void();
  pushdown(x);
  int mid = l + r >> 1;
  if (pos <= mid)
    query(x << 1, pos, l, mid, res);
  else
    query(x << 1 | 1, pos, mid + 1, r, res);
  pushup(x);
}
void dfs(int x, int _fa, int _dep) {
  fa[x] = _fa, dep[x] = _dep, sz[x] = 1;
  for (auto &v : nxt[x]) {
    if (v != _fa) {
      dfs(v, x, _dep + 1), sz[x] += sz[v];
      if (sz[v] > sz[son[x]])
        son[x] = v;
    }
  }
}
void dfs_2(int x, int _top) {
  top[x] = _top, dfn[x] = ++cnt;
  if (son[x])
    dfs_2(son[x], _top);
  for (auto &v : nxt[x]) {
    if (v != fa[x] && v != son[x])
      dfs_2(v, v);
  }
}
int main() {
  read(n);
  for (int i = 1, u, v; i <= n - 1; i++) {
    read(u), read(v), nxt[u].pb(v), nxt[v].pb(u);
  }
  dfs(1, 0, 1), dfs_2(1, 1), build(1, 2, n);
  for (int i = 1, u, v; i <= n - 1; i++) {
    read(u), read(v), es[i].u = u, es[i].v = v;
    while (top[u] != top[v]) {
      if (dep[top[u]] < dep[top[v]])
        swap(u, v);
      update(1, dfn[top[u]], dfn[u], 2, n, i), u = fa[top[u]];
    }
    if (dep[u] > dep[v])
      swap(u, v);
    update(1, dfn[u] + 1, dfn[v], 2, n, i);
  }
  for (int i = 1, res; i <= n - 1; i++) {
    if (t[1].fi > 1)
      return puts("NO"), 0;
    query(1, t[1].se, 2, n, res);
    int u = es[res].u, v = es[res].v;
    vis[res] = true;
    while (top[u] != top[v]) {
      if (dep[top[u]] < dep[top[v]])
        swap(u, v);
      update(1, dfn[top[u]], dfn[u], 2, n, -1), u = fa[top[u]];
    }
    if (dep[u] > dep[v])
      swap(u, v);
    update(1, dfn[u] + 1, dfn[v], 2, n, -1);
  }
  puts("YES");
  return 0;
}

Measured memory_bytes: 54144