#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

const long long INF = 1e18;
//const ll mod = 1000000007;
typedef vector<vector<int>> UnWeightedGraph;
ll N;
vector<ll> c, d;

struct LazySegmentTree {
private:
    int n;
    vector<ll> node, lazy;

public:
    LazySegmentTree() {
        int sz = 100050;
        n = 1; while(n < sz) n *= 2;
        node.resize(2*n-1);
        lazy.resize(2*n-1, 0);

        for(int i=0; i<sz; i++) node[i+n-1] = 0;
        for(int i=n-2; i>=0; i--) node[i] = node[i*2+1] + node[i*2+2];
    }
    void eval(int k, int l, int r) {
        if(lazy[k] != 0) {
            node[k] ^= lazy[k];
            if(r - l > 1) {
                lazy[2*k+1] ^= lazy[k];
                lazy[2*k+2] ^= lazy[k];
            }
            lazy[k] = 0;
        }
    }

    void add(int a, int b, ll x, int k=0, int l=0, int r=-1) {
        if(r < 0) r = n;
        eval(k, l, r);
        if(b <= l || r <= a) return;
        if(a <= l && r <= b) {
            lazy[k] ^= x;
            eval(k, l, r);
        }
        else {
            add(a, b, x, 2*k+1, l, (l+r)/2);
            add(a, b, x, 2*k+2, (l+r)/2, r);
            node[k] = node[2*k+1] ^ node[2*k+2];
        }
    }

    ll getxor(int a, int b, int k=0, int l=0, int r=-1) {
        if(r < 0) r = n;
        eval(k, l, r);

        if(b <= l || r <= a) return 0;
        if(a <= l && r <= b) return node[k];
        ll vl = getxor(a, b, 2*k+1, l, (l+r)/2);
        ll vr = getxor(a, b, 2*k+2, (l+r)/2, r);
        return vl ^ vr;
    }

};



struct LazySegmentTree2 {
private:
    int n;
    vector<ll> lazy;
    vector<l_l> node;

public:
    LazySegmentTree2() {
        int sz = 100100;
        n = 1; while(n < sz) n *= 2;
        node.resize(2*n-1);
        lazy.resize(2*n-1, 0);

        for(int i=0; i<sz; i++) node[i+n-1] = {0, i};
        for(int i=n-2; i>=0; i--) node[i] = min(node[i*2+1], node[i*2+2]);
    }
    void eval(int k, int l, int r) {
        if(lazy[k] != 0) {
            node[k].first += lazy[k];
            if(r - l > 1) {
                lazy[2*k+1] += lazy[k];
                lazy[2*k+2] += lazy[k];
            }
            lazy[k] = 0;
        }
    }

    void add(int a, int b, ll x, int k=0, int l=0, int r=-1) {
        if(r < 0) r = n;
        eval(k, l, r);
        if(b <= l || r <= a) return;
        if(a <= l && r <= b) {
            lazy[k] += x;
            eval(k, l, r);
        }
        else {
            add(a, b, x, 2*k+1, l, (l+r)/2);
            add(a, b, x, 2*k+2, (l+r)/2, r);
            node[k] = min(node[2*k+1], node[2*k+2]);
        }
    }

    l_l getmin(int a, int b, int k=0, int l=0, int r=-1) {
        if(r < 0) r = n;
        eval(k, l, r);

        if(b <= l || r <= a) return {1e9, 0};
        if(a <= l && r <= b) return node[k];
        auto vl = getmin(a, b, 2*k+1, l, (l+r)/2);
        auto vr = getmin(a, b, 2*k+2, (l+r)/2, r);
        return min(vl, vr);
    }

};



struct HLDecomposition {
  int n,pos;
  vector<vector<int> > G;
  vector<int> vid, head, sub, hvy, par, dep, inv, type;
  
  HLDecomposition(){}
  HLDecomposition(int sz):
    n(sz),pos(0),G(n),
    vid(n,-1),head(n),sub(n,1),hvy(n,-1),
    par(n),dep(n),inv(n),type(n){}
  
  void add_edge(int u, int v) {
    G[u].push_back(v);
    G[v].push_back(u);
  }

  void build(vector<int> rs=vector<int>(1,0)) {
    int c=0;
    for(int r:rs){
      dfs(r);
      bfs(r, c++);
    }
  }
  
  void dfs(int rt) {
    using T = pair<int,int>;
    stack<T> st;
    par[rt]=-1;
    dep[rt]=0;
    st.emplace(rt,0);
    while(!st.empty()){
      int v=st.top().first;
      int &i=st.top().second;
      if(i<(int)G[v].size()){
	int u=G[v][i++];
	if(u==par[v]) continue;
	par[u]=v;
	dep[u]=dep[v]+1;
	st.emplace(u,0);
      }else{
	st.pop();
	int res=0;
	for(int u:G[v]){
	  if(u==par[v]) continue;
	  sub[v]+=sub[u];
	  if(res<sub[u]) res=sub[u],hvy[v]=u;
	}
      }
    }
  }

  void bfs(int r,int c) {
    int &k=pos;
    queue<int> q({r});
    while(!q.empty()){
      int h=q.front();q.pop();
      for(int i=h;i!=-1;i=hvy[i]) {
	type[i]=c;
	vid[i]=k++;
	inv[vid[i]]=i;
	head[i]=h;
	for(int j:G[i])
	  if(j!=par[i]&&j!=hvy[i]) q.push(j);
      }
    }
  }
  
  // for_each(vertex)
  // [l,r] <- attention!!
  void for_each(int u, int v, const function<void(int, int)>& f) {
    while(1){
      if(vid[u]>vid[v]) swap(u,v);
      f(max(vid[head[v]],vid[u]),vid[v]);
      if(head[u]!=head[v]) v=par[head[v]];
      else break;
    }
  }
  
  // for_each(edge)
  // [l,r] <- attention!!
  void for_each_edge(int u, int v, const function<void(int, int)>& f) {
    while(1){
      if(vid[u]>vid[v]) swap(u,v);
      if(head[u]!=head[v]){
	f(vid[head[v]],vid[v]);
        v=par[head[v]];
      } else{
	if(u!=v) f(vid[u]+1,vid[v]);
	break;
      }
    }
  }

  int lca(int u,int v){
    while(1){
      if(vid[u]>vid[v]) swap(u,v);
      if(head[u]==head[v]) return u;
      v=par[head[v]];
    }
  }

  int distance(int u,int v){
    return dep[u]+dep[v]-2*dep[lca(u,v)];
  }
};

int main() {
    cin >> N;
    HLDecomposition HLD(N);
    for(int i = 0; i < N - 1; i++) {
        ll a, b;
        cin >> a >> b;
        a--;
        b--;
        HLD.add_edge(a, b);
    }
    HLD.build();
    c.resize(N - 1), d.resize(N - 1);
    for(int i = 0; i < N - 1; i++) {
        cin >> c[i] >> d[i];
        c[i]--;
        d[i]--;
    }
    LazySegmentTree seg;
    LazySegmentTree2 seg2;
    int delta = 1;
    auto f = [&](int a, int b) {
        //cerr << HLD.inv[a] << " " << HLD.inv[b] << endl;
        seg2.add(a, b + 1, delta);
    };
    int edge;
    auto g = [&](int a, int b) {
        seg.add(a, b + 1, edge);
    };
    for(edge = 0; edge < N - 1; edge++) {
        HLD.for_each_edge(c[edge], d[edge], f);
        HLD.for_each_edge(c[edge], d[edge], g);
    }
    for(int timer = 1; timer < N; timer++) {
        auto tmp = seg2.getmin(1, N);
        if(tmp.first != 1) {
            cout << "NO" << endl;
            return 0;
        }
        int idx = tmp.second;
        int v = HLD.inv[idx];
        int e = seg.getxor(idx, idx + 1);
        //cerr << idx << " " << v << " " << e << endl;
        delta = -1;
        HLD.for_each_edge(c[e], d[e], f);
        delta = 1e6;
        seg2.add(idx, idx + 1, delta);
        edge = e;
        HLD.for_each_edge(c[edge], d[edge], g);
    }
    cout << "YES" << endl;
    /*
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
            //cerr << "-------" << i << "------" << j << "------" << endl;
            //cerr << "distance: " << HLD.distance(i, j) << endl;
            HLD.for_each_edge(i, j, f);
            cerr << i << " " << j << " " << seg2.getmin(1, N).first << " " << seg2.getmin(1, N).second << endl;
        }
    }
    */
    return 0;
}


Measured memory_bytes: 20992