/*Program from Luvwgyx*/
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
const int maxn=1e5+10;
struct edge{int to,nxt;}e[maxn<<1];
int n,tot,idx=-1,pos,head[maxn],dfn[maxn],del[maxn],a[maxn],b[maxn],c[maxn],d[maxn];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void print(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)print(x/10);
    putchar(x%10+'0');
}
void write(int x){print(x);puts("");}
void add(int u,int v){e[++tot].to=v;e[tot].nxt=head[u];head[u]=tot;}
struct Segment_Tree{
    struct node{int w,f;vector<int >id;}tree[maxn<<2];
    void update(int k){tree[k].w=min(tree[k<<1].w,tree[k<<1|1].w);}
    void down(int k){
        if(tree[k].f){
            tree[k<<1].w+=tree[k].f;tree[k<<1|1].w+=tree[k].f;
            tree[k<<1].f+=tree[k].f;tree[k<<1|1].f+=tree[k].f;
            tree[k].f=0;
        }
    }
    void insert(int k,int l,int r,int x,int y,int v){
        if(x<=l&&r<=y){tree[k].id.push_back(v);tree[k].w++;tree[k].f++;return ;}
        down(k);int mid=(l+r)>>1;
        if(x<=mid)insert(k<<1,l,mid,x,y,v);
        if(mid<y)insert(k<<1|1,mid+1,r,x,y,v);
        update(k);
    }
    void change(int k,int l,int r,int x,int y,int v){
        if(x<=l&&r<=y){tree[k].w+=v;tree[k].f+=v;return ;}
        down(k);int mid=(l+r)>>1;
        if(x<=mid)change(k<<1,l,mid,x,y,v);
        if(mid<y)change(k<<1|1,mid+1,r,x,y,v);
        update(k);
    }
    int query(int k,int l,int r){
        if(tree[k].w>1)return -1;int ret=0;
        while(!tree[k].id.empty()&&del[tree[k].id.back()])tree[k].id.pop_back();
        if(!tree[k].id.empty())ret=tree[k].id.back();
        if(l==r){pos=l;return ret;}int mid=(l+r)>>1,now;down(k);
        now=query(k<<1,l,mid);if(now!=-1){if(now)return now;if(ret)return ret;}
        now=query(k<<1|1,mid+1,r);if(now!=-1){if(now)return now;if(ret)return ret;}
        return ret;
    }
}T;
struct Heavy_Light_Decomposition{
    int dep[maxn],size[maxn],fa[maxn],top[maxn],son[maxn];
    void build(int x,int deep){
        dep[x]=deep;size[x]=1;int mx=0;
        for(int i=head[x],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
            if(v!=fa[x]){
                fa[v]=x;build(v,deep+1);size[x]+=size[v];
                if(size[v]>mx)mx=size[v],son[x]=v;
            }
    }
    void dfs(int x){
        if(!x)return ;dfn[x]=++idx;
        top[x]=son[fa[x]]==x?top[fa[x]]:x;dfs(son[x]);
        for(int i=head[x],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
            if(v!=fa[x]&&v!=son[x])dfs(v);
    }
    void insert(int x,int y,int id){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            T.insert(1,1,n-1,dfn[top[x]],dfn[x],id);
            x=fa[top[x]];
        }if(dfn[x]>dfn[y])swap(x,y);
        if(x!=y)T.insert(1,1,n-1,dfn[x]+1,dfn[y],id);
    }
    void change(int x,int y,int v){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            T.change(1,1,n-1,dfn[top[x]],dfn[x],v);
            x=fa[top[x]];
        }if(dfn[x]>dfn[y])swap(x,y);
        if(x!=y)T.change(1,1,n-1,dfn[x]+1,dfn[y],v);
    }
}HLD;
signed main(){
    n=read();
    for(int i=1;i<n;i++){
        a[i]=read();b[i]=read();
        add(a[i],b[i]);add(b[i],a[i]);
    }HLD.build(1,1);HLD.dfs(1);
    for(int i=1;i<n;i++){
        c[i]=read();d[i]=read();
        HLD.insert(c[i],d[i],i);
        //write(T.tree[1].w);
    }
    for(int i=1;i<n;i++){
        if(T.tree[1].w!=1){puts("NO");return 0;}
        int now=T.query(1,1,n-1);del[now]=1;
        T.change(1,1,n-1,pos,pos,maxn);
        HLD.change(c[now],d[now],-1);
    }puts("YES");
    return 0;
}


Measured memory_bytes: 51532