#include<bits/stdc++.h>
#define lc (x<<1)
#define rc (x<<1|1) 
using namespace std;
const int N=100006,inf=1e9;
int n,t1,t2,cnt=0,dfn=0,del=0,tot=0,f[N],d[N],v[N<<2],vis[N],son[N],siz[N],num[N],top[N],lazy[N<<2],head[N],p[N],q[N];
struct edge{int nxt,to;}e[N<<1];
map<int,bool>ha[N];
inline void add(int u,int v){e[++cnt].nxt=head[u],e[cnt].to=v,head[u]=cnt;}
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
struct xd{int z,i;}w[N<<2];
void dfs(int x,int fa){
     f[x]=fa,d[x]=d[fa]+1,siz[x]=1; int maxt=0,maxa=-1;
     for(int i=head[x];i;i=e[i].nxt)
         if(e[i].to!=fa){
            dfs(e[i].to,x),siz[x]+=siz[e[i].to];
            if(maxa<siz[e[i].to]) maxt=e[i].to,maxa=siz[maxt];
         } 
     son[x]=maxt;
}
void dfs2(int x,int topx){
     num[x]=++dfn,top[x]=topx;
     if(son[x]) dfs2(son[x],topx);
     for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=f[x]&&e[i].to!=son[x]) dfs2(e[i].to,e[i].to); 
}
void pushdown(int x){
     if(lazy[x]!=0) lazy[lc]+=lazy[x],lazy[rc]+=lazy[x],w[lc].z+=lazy[x],w[rc].z+=lazy[x],lazy[x]=0;
     if(v[x]!=0) v[lc]^=v[x],v[rc]^=v[x],v[x]=0;
}
void pushup(int x){
     if(w[lc].z<w[rc].z) w[x]=w[lc];
     else w[x]=w[rc];
}
void build(int l,int r,int x){
     if(l==r){w[x].i=l,w[x].z=vis[l]?inf:0; return;}
     int mid=l+r>>1;
     build(l,mid,lc),build(mid+1,r,rc);
     pushup(x);
}
void update(int l,int r,int p,int q,int x,int y){
    if(p<=l&&r<=q){++lazy[x],++w[x].z,v[x]^=y; return;}
    pushdown(x);
    int mid=l+r>>1;
    if(p<=mid) update(l,mid,p,q,lc,y);
    if(q>mid) update(mid+1,r,p,q,rc,y);
    pushup(x);
}
void update2(int l,int r,int p,int x){
    if(l==r){w[x].z=inf; return;}
    pushdown(x);
    int mid=l+r>>1;
    if(p<=mid) update2(l,mid,p,lc);
    else update2(mid+1,r,p,rc);
    pushup(x);
}
void update3(int l,int r,int p,int q,int x,int y){
    if(p<=l&&r<=q){--lazy[x],--w[x].z,v[x]^=y; return;}
    pushdown(x);
    int mid=l+r>>1;
    if(p<=mid) update3(l,mid,p,q,lc,y);
    if(q>mid) update3(mid+1,r,p,q,rc,y);
    pushup(x);
}
int query(int l,int r,int p,int x){
    if(l==r) return v[x];
    int mid=l+r>>1;
    pushdown(x);
    if(p<=mid) return query(l,mid,p,lc);
    return query(mid+1,r,p,rc); 
}
void lj_update(int x,int y,int z){
    while(top[x]!=top[y]){
         if(d[top[x]]<d[top[y]]) swap(x,y);
         update(1,n,num[top[x]],num[x],1,z);
         x=f[top[x]];
    }
    if(d[x]>d[y]) swap(x,y);
    update(1,n,num[x]+1,num[y],1,z);
}
void lj_update3(int x,int y,int z){
    while(top[x]!=top[y]){
         if(d[top[x]]<d[top[y]]) swap(x,y);
         update3(1,n,num[top[x]],num[x],1,z);
         x=f[top[x]];
    }
    if(d[x]>d[y]) swap(x,y);
    update3(1,n,num[x]+1,num[y],1,z);
}
int main(){
    n=read();
    for(int i=1;i<n;++i) t1=read(),t2=read(),add(t1,t2),add(t2,t1),ha[t1][t2]=1,ha[t2][t1]=1;
    dfs(1,0),dfs2(1,1);
    for(int i=1;i<n;++i){
        p[i]=read(),q[i]=read(),t1=p[i],t2=q[i]; 
        if(ha[t1].find(t2)!=ha[t1].end()) vis[num[t1]>num[t2]?num[t1]:num[t2]]=1; 
    }
    build(1,n,1); 
    for(int i=1;i<n;++i)
        if(ha[p[i]].find(q[i])==ha[p[i]].end()) ++tot,lj_update(p[i],q[i],i);
    while(true){
         if(w[1].z>1) break;
         if(!w[1].z){update2(1,n,w[1].i,1); continue;}
         ++del,t1=query(1,n,w[1].i,1),lj_update3(p[t1],q[t1],t1);
    }
    if(tot==del) printf("YES\n");
    else printf("NO\n");
    return 0;
}  

Measured memory_bytes: 31616