// {{{ by shik
// #include <stdio.h>
#include <bits/stdc++.h>
#include <unistd.h>
#define SZ(x) ((int)(x).size())
#define ALL(x) begin(x),end(x)
#define REP(i,n) for ( int i=0; i<int(n); i++ )
#define REP1(i,a,b) for ( int i=(a); i<=int(b); i++ )
#define FOR(it,c) for ( auto it=(c).begin(); it!=(c).end(); it++ )
#define MP make_pair
#define PB push_back
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef vector<int> VI;

#ifdef SHIK
template<typename T>
void _dump( const char* s, T&& head ) { cerr<<s<<"="<<head<<endl; }

template<typename T, typename... Args>
void _dump( const char* s, T&& head, Args&&... tail ) {
    int c=0;
    while ( *s!=',' || c!=0 ) {
        if ( *s=='(' || *s=='[' || *s=='{' ) c++;
        if ( *s==')' || *s==']' || *s=='}' ) c--;
        cerr<<*s++;
    }
    cerr<<"="<<head<<", ";
    _dump(s+1,tail...);
}

#define dump(...) do { \
    fprintf(stderr, "%s:%d - ", __PRETTY_FUNCTION__, __LINE__); \
    _dump(#__VA_ARGS__, __VA_ARGS__); \
} while (0)

template<typename Iter>
ostream& _out( ostream &s, Iter b, Iter e ) {
    s<<"[";
    for ( auto it=b; it!=e; it++ ) s<<(it==b?"":" ")<<*it;
    s<<"]";
    return s;
}

template<typename A, typename B>
ostream& operator <<( ostream &s, const pair<A,B> &p ) { return s<<"("<<p.first<<","<<p.second<<")"; }
template<typename T>
ostream& operator <<( ostream &s, const vector<T> &c ) { return _out(s,ALL(c)); }
template<typename T, size_t N>
ostream& operator <<( ostream &s, const array<T,N> &c ) { return _out(s,ALL(c)); }
template<typename T>
ostream& operator <<( ostream &s, const set<T> &c ) { return _out(s,ALL(c)); }
template<typename A, typename B>
ostream& operator <<( ostream &s, const map<A,B> &c ) { return _out(s,ALL(c)); }
#else
#define dump(...)
#endif

template<typename T>
void _R( T &x ) { cin>>x; }
void _R( int &x ) { scanf("%d",&x); }
void _R( long long &x ) { scanf("%" PRId64,&x); }
void _R( double &x ) { scanf("%lf",&x); }
void _R( char &x ) { scanf(" %c",&x); }
void _R( char *x ) { scanf("%s",x); }

void R() {}
template<typename T, typename... U>
void R( T& head, U&... tail ) {
    _R(head);
    R(tail...);
}

template<typename T>
void _W( const T &x ) { cout<<x; }
void _W( const int &x ) { printf("%d",x); }
void _W( const long long &x ) { printf("%" PRId64,x); }
template<typename T>
void _W( const vector<T> &x ) {
    for ( auto i=x.cbegin(); i!=x.cend(); i++ ) {
        if ( i!=x.cbegin() ) putchar(' ');
        _W(*i);
    }
}

void W() {}
template<typename T, typename... U>
void W( const T& head, const U&... tail ) {
    _W(head);
    putchar(sizeof...(tail)?' ':'\n');
    W(tail...);
}

template<typename T> inline bool chkmax(T &a, const T &b) { return b > a ? a = b, true : false; }
template<typename T> inline bool chkmin(T &a, const T &b) { return b < a ? a = b, true : false; }

#ifdef SHIK
#define FILEIO(...)
#else
#define FILEIO(name) do {\
    freopen(name ".in","r",stdin); \
    freopen(name ".out","w",stdout); \
} while (0)
#endif

// }}}

#define FOR(it,c) for ( auto it=(c).begin(); it!=(c).end(); it++ )

const int N=100010;
const int M=4*N;
struct Seg {
    int add[M],mix[M];
    array<int,3> mi[M];
    void init( int id, int l, int r ) {
        if ( l==r ) {
            add[id]=0;
            mix[id]=0;
            mi[id]={{0,0,l}};
            return;
        }
        int m=(l+r)/2;
        init(id*2,l,m);
        init(id*2+1,m+1,r);
    }
    array<int,3> get_mi( int id ) {
        return {{mi[id][0]+add[id],mi[id][1]^mix[id],mi[id][2]}};
    }
    void pull( int id ) {
        mi[id]=min(get_mi(id*2),get_mi(id*2+1));
    }
    void ins( int id, int l, int r, int ql, int qr, int qa, int qs ) {
        if ( ql<=l && r<=qr ) {
            // dump(id,l,r,ql,qr,qa,qs);
            add[id]+=qa;
            mix[id]^=qs;
            return;
        }
        int m=(l+r)/2;
        if ( ql<=m ) ins(id*2,l,m,ql,qr,qa,qs);
        if ( qr>m ) ins(id*2+1,m+1,r,ql,qr,qa,qs);
        pull(id);
        // dump(id,l,r,get_mi(id));
    }
} seg;

int n;
VI e[N];

int sz[N];
int get_sz( int p, int f ) {
    sz[p]=1;
    FOR(it,e[p]) if ( *it!=f ) sz[p]+=get_sz(*it,p);
    return sz[p];
}

int st[N],ed[N],pid,fa[N],dep[N],root[N];
void dfs( int p, int f, int lv ) {
    st[p]=++pid;
    fa[p]=f;
    dep[p]=lv;
    int w=0;
    FOR(it,e[p]) if ( *it!=f && (!w || sz[*it]>sz[w]) ) w=*it;
    if ( w ) {
        root[w]=root[p];
        dfs(w,p,lv+1);
        FOR(it,e[p]) if ( *it!=f && *it!=w ) {
            root[*it]=*it;
            dfs(*it,p,lv+1);
        }
    }
    ed[p]=pid;
}

void build() {
    get_sz(1,0);
    root[1]=1;
    pid=0;
    dfs(1,0,1);
    REP1(i,1,n) dump(i,st[i]);
    seg.init(1,1,n);
}

vector<PII> get_path( int a, int b ) {
   vector<PII> v;
   while ( root[a]!=root[b] ) {
       if ( dep[root[a]]>dep[root[b]] ) swap(a,b);
       v.PB(MP(st[root[b]],st[b]));
       b=fa[root[b]];
   }
   if ( dep[a]>dep[b] ) swap(a,b);
   if ( a!=b ) v.PB(MP(st[a]+1,st[b]));
   return v;
}

int main() {
    R(n);
    REP(i,n-1) {
        int a,b;
        R(a,b);
        e[a].PB(b);
        e[b].PB(a);
    }
    build();
    vector<PII> e2(n-1);
    REP(i,n-1) R(e2[i].first,e2[i].second);
    REP(i,n-1) {
        auto p=get_path(e2[i].first,e2[i].second);
        dump(e2[i],p);
        for ( auto j:p ) {
            seg.ins(1,1,n,j.first,j.second,+1,i);
        }
    }
    seg.ins(1,1,n,1,1,N,0);
    REP(i,n-1) {
        auto x=seg.get_mi(1);
        dump(i,x);
        if ( x[0]!=1 ) {
            W("NO");
            return 0;
        }
        int id=x[1];
        assert(0<=id && id<n-1);
        auto p=get_path(e2[id].first,e2[id].second);
        for ( auto j:p ) {
            seg.ins(1,1,n,j.first,j.second,-1,id);
        }
        seg.ins(1,1,n,x[2],x[2],N,0);
    }
    W("YES");
    return 0;
}


Measured memory_bytes: 23424