#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;
typedef pair<ii, int> ri3;
#define mp make_pair
#define pb push_back
#define fi first
#define sc second
#define SZ(x) (int)(x).size()
#define ALL(x) begin(x), end(x) 
#define REP(i, n) for (int i = 0; i < n; ++i) 
#define FOR(i, a, b) for (int i = a; i <= b; ++i)
#define RFOR(i, a, b) for (int i = a; i >= b; --i)

const int MX_N = 1e5+5;

int N;
int C[MX_N], D[MX_N];

struct node {
    int s, e, m;
    set<int> pth; array<int,3> val;
    node *l, *r;
    node(int s, int e): s(s), e(e), m((s+e)/2), val({0,s,-1}) {
        if (s != e) {
            l = new node(s,m);
            r = new node(m+1,e);
        }
    }

    void update(int x, int y, int v) {
        if (s == x && e == y) {
            if (v < 0) pth.erase(-v);
            else pth.insert(v);
            if (s == e) {
                if (pth.empty()) val = {0,s,-1};
                else val = {SZ(pth),s,*pth.begin()};
                return;
            }
        } else if (y <= m) l->update(x,y,v);
        else if (x > m) r->update(x,y,v);
        else l->update(x,m,v), r->update(m+1,y,v);

        if (l->val < r->val) val = l->val;
        else val = r->val;
        val[0] += SZ(pth);
        if (val[2] == -1 && !pth.empty()) val[2] = *pth.begin();
    }

    void update(int x, int v) {
        if (s == e) {
            val = {v,s,-1};
            return;
        } else if (x <= m) l->update(x,v);
        else r->update(x,v);

        if (l->val < r->val) val = l->val;
        else val = r->val;
        val[0] += SZ(pth);
        if (val[2] == -1 && !pth.empty()) val[2] = *pth.begin();
    }

    array<int,3> query(int x, int y) {
        if (s == x && e == y) return val;
        else if (y <= m) return l->query(x,y);
        else if (x > m) return r->query(x,y);
        else {
            auto q1 = l->query(x,m), q2 = r->query(m+1,y);
            return min(q1,q2);
        }
    }

    void dbg() {
        cout << s << " " << e << " :: " << SZ(pth) << " " << val[0] << " " << val[1] << " " << val[2] << endl;
        if (s != e) {
            l->dbg();
            r->dbg();
        }
    }
};

struct graph {
    node* root;
    vector<int> al[MX_N];

    int pa[MX_N], dep[MX_N], cnt, pre[MX_N], head[MX_N], heavy[MX_N];
    void hld(int u, int p=0) {
        dfs(u,p,0);
        cnt = 0;
        decomp(u,p,u);
        root = new node(2,cnt);
    }

    int dfs(int u, int p, int d) {
        pa[u] = p;
        dep[u] = d;
        heavy[u] = -1;
        int sz = 1, mchild = 0;
        for (auto& v : al[u]) if (v != p) {
            int cs = dfs(v,u,d+1);
            sz += cs;
            if (cs > mchild) mchild = cs, heavy[u] = v;
        }
        return sz;
    }

    void decomp(int u, int p, int h) {
        head[u] = h;
        pre[u] = ++cnt;
        if (heavy[u] != -1) decomp(heavy[u],u,h);
        for (auto& v : al[u]) if (v != p && v != heavy[u]) {
            decomp(v,u,v);
        }
    }

    void update_path(int a, int b, int v) {
        for (; head[a] != head[b]; a = pa[head[a]]) {
            if (dep[head[a]] < dep[head[b]]) swap(a,b);
            root->update(pre[head[a]],pre[a],v);
        }
        if (a == b) return;
        if (dep[a] < dep[b]) swap(a,b);
        //cout << "UPDATE " << pre[b]+1 << " " << a << endl;
        root->update(pre[b]+1,pre[a],v);
    }

    array<int,3> get_min_edge() {
        auto q = root->query(2,cnt);
        return q;
    }
} g;

int main() {
    //freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> N;
    FOR(i,1,N-1){
        int a,b; cin >> a >> b;
        g.al[a].push_back(b);
        g.al[b].push_back(a);
    }

    g.hld(1);

    FOR(i,1,N-1){
        cin >> C[i] >> D[i];
        g.update_path(C[i],D[i],i);
    }
    //g.root->dbg();

    int ok = 0;
    while (true) {
        auto e = g.get_min_edge();
        if (e[0] != 1) break;
        //cout << "GOT " << e[0] << " " << e[1] << " " << e[2] << endl;
        g.update_path(C[e[2]],D[e[2]],-e[2]);
        g.root->update(e[1],MX_N);  // only 1 edge like this
        ++ok;
        //g.root->dbg();

    }
    cout << (ok == N-1 ? "YES" : "NO");
}



Measured memory_bytes: 126336