#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cmath>
#include <iomanip>
#include <cassert>
#include <bitset>
#include <functional>
using namespace std;

typedef pair<int, int> P;
#define rep(i, n) for (int i=0; i<(n); i++)
#define all(c) (c).begin(), (c).end()
#define uniq(c) c.erase(unique(all(c)), (c).end())
#define index(xs, x) (int)(lower_bound(all(xs), x) - xs.begin())
#define _1 first
#define _2 second
#define pb push_back
#define INF 11451411
#define MOD 1000000007
struct HLDecomposition {
  int N;
  vector<vector<int> > G;
  vector<int> next, par, head, tid, rev;
  HLDecomposition(int N) : N(N), G(N), next(N, -1), par(N, -1), head(N, -1), tid(N, -1), rev(N, -1) {}
  void add_edge(int x, int y) {
    G[x].pb(y);
    G[y].pb(x);
  }
  int dfs(int x, int p) {
    par[x] = p;
    int sz = 1, cur = 0;
    for (int t : G[x]) if (t != p) {
      int c = dfs(t, x);
      sz += c;
      if (cur < c) cur = c, next[x] = t;
    }
    return sz;
  }
  void build() {
    assert(dfs(0, -1) == N);
    bfs(0);
  }
  void bfs(int s) {
    int k = 0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
      int h = q.front(); q.pop();
      for (int x=h; x!=-1; x=next[x]) {
        head[x] = h, rev[k] = x, tid[x] = k++;
        for (int t : G[x]) if (t != par[x] && t != next[x]) q.push(t);
      }
      //for (int x=h; x!=-1; x=next[x]) for (int t : G[x]) if (tid[t] == -1) q.push(t);
    }
    assert(k == N);
  }
  void for_each(int u, int v, function<void(int, int)> f) {
    if (u == v) return;
    if (tid[u] > tid[v]) swap(u, v);
    if (head[u] == head[v]) return f(tid[u]+1, tid[v]);
    if (tid[head[u]] > tid[head[v]]) swap(u, v);
    f(tid[head[v]], tid[v]);
    for_each(u, par[head[v]], f);
  }
};

bool used[100000];
#define MAX_N (1<<17)
struct SegTree {
  vector<int> seg[MAX_N*2-1];
  void add(int a, int b, int x, int k=0, int l=0, int r=MAX_N) {
    if (b <= l || r <= a) return;
    if (a <= l && r <= b) {
      seg[k].pb(x);
      return;
    }
    add(a, b, x, k*2+1, l, (l+r)/2);
    add(a, b, x, k*2+2, (l+r)/2, r);
  }
  int query(int a, int b, int k=0, int l=0, int r=MAX_N) {
    if (b <= l || r <= a) return -1;
    while (!seg[k].empty() && used[seg[k].back()]) seg[k].pop_back();
    if (!seg[k].empty()) return seg[k].back();
    if (a <= l && r <= b) return -1;
    return max(query(a, b, k*2+1, l, (l+r)/2), query(a, b, k*2+2, (l+r)/2, r));
  }
};

struct SegTree2 {
  P seg[MAX_N*2-1] = {};
  int lazy[MAX_N*2-1] = {};
  SegTree2(int N) {
    rep(i, MAX_N*2-1) seg[i] = P(2, -1);
    rep(i, N) seg[i+MAX_N-1] = P(0, i);
    for (int i=MAX_N-2; i>=0; i--) seg[i] = min(seg[i*2+1], seg[i*2+2]);
  }
  void setLazy(int k, int v) {
    seg[k]._1 += v;
    lazy[k] += v;
  }
  void push(int k) {
    if (lazy[k] == 0) return;
    setLazy(k*2+1, lazy[k]);
    setLazy(k*2+2, lazy[k]);
    lazy[k] = 0;
  }
  void add(int a, int b, int val, int k=0, int l=0, int r=MAX_N) {
    if (b <= l || r <= a) return;
    if (a <= l && r <= b) return setLazy(k, val);
    push(k);
    add(a, b, val, k*2+1, l, (l+r)/2);
    add(a, b, val, k*2+2, (l+r)/2, r);
    seg[k] = min(seg[k*2+1], seg[k*2+2]);
  }
  P query(int a, int b, int k=0, int l=0, int r=MAX_N) {
    if (b <= l || r <= a) return P(2, -1);
    if (a <= l && r <= b) return seg[k];
    push(k);
    return min(query(a, b, k*2+1, l, (l+r)/2), query(a, b, k*2+2, (l+r)/2, r));
  }
};

int N;
vector<int> G[100000];
int C[100000], D[100000];
SegTree seg;

signed main() {
  ios::sync_with_stdio(false); cin.tie(0);
  cin >> N;
  SegTree2 seg2(N);
  HLDecomposition hld(N);
  rep(i, N-1) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    hld.add_edge(a, b);
  }
  hld.build();
  seg2.add(hld.tid[0], hld.tid[0]+1, 2);

  rep(i, N-1) {
    cin >> C[i] >> D[i];
    C[i]--, D[i]--;
    hld.for_each(C[i], D[i], [&](int l, int r) {
      seg.add(l, r+1, i);
      seg2.add(l, r+1, 1);
    });
  }
  rep(_, N-1) {
    if (seg2.seg[0]._1 != 1) {
      cout << "NO\n";
      return 0;
    }
    int pos = seg2.seg[0]._2;
    int id = seg.query(pos, pos+1);
    assert(id != -1);
    seg2.add(pos, pos+1, 2); // +INF
    used[id] = true;
    hld.for_each(C[id], D[id], [&](int l, int r) { seg2.add(l, r+1, -1); });
  }
  cout << "YES\n";
  return 0;
}


Measured memory_bytes: 36172