#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define fst first
#define snd second
#define fore(i,a,b) for(int i=a,ThxDem=b;i<ThxDem;++i)
using namespace std;
typedef long long ll;

struct STree { // example: range sum with range addition
	vector<pair<int,int> > st;
	vector<int> lazy;int n;
	vector<set<int> > w;
	STree(int n): st(4*n+5,mp(10,10)), lazy(4*n+5,0), w(4*n+5), n(n) {}
	void init(int k, int s, int e){
		lazy[k]=0;  // lazy neutral element
		if(s+1==e){st[k]=mp(0,s);return;}
		int m=(s+e)/2;
		init(2*k,s,m);init(2*k+1,m,e);
		st[k]=min(st[2*k],st[2*k+1]); // operation
	}
	void push(int k, int s, int e){
		if(!lazy[k])return; // if neutral, nothing to do
		st[k].fst+=lazy[k]; // update st according to lazy
		if(s+1<e){ // propagate to children
			lazy[2*k]+=lazy[k];
			lazy[2*k+1]+=lazy[k];
		}
		lazy[k]=0; // clear node lazy
	}
	void add(int k, int s, int e, int a, int b, int v){
		push(k,s,e);
		if(s>=b||e<=a)return;
		if(s>=a&&e<=b){
			lazy[k]++; // accumulate lazy
			w[k].insert(v);
			push(k,s,e);return;
		}
		int m=(s+e)/2;
		add(2*k,s,m,a,b,v);add(2*k+1,m,e,a,b,v);
		st[k]=min(st[2*k],st[2*k+1]); // operation
	}
	void del(int k, int s, int e, int a, int b, int v){
		push(k,s,e);
		if(s>=b||e<=a)return;
		if(s>=a&&e<=b){
			lazy[k]--; // accumulate lazy
			w[k].erase(v);
			push(k,s,e);return;
		}
		int m=(s+e)/2;
		del(2*k,s,m,a,b,v);del(2*k+1,m,e,a,b,v);
		st[k]=min(st[2*k],st[2*k+1]); // operation
	}
	void asd(int k, int s, int e){
		push(k,s,e);
		if(st[k].fst)return;
		if(s+1==e){st[k].fst=1<<20;return;}
		int m=(s+e)/2;
		asd(2*k,s,m);
		asd(2*k+1,m,e);
		st[k]=min(st[2*k],st[2*k+1]); // operation
	}
	pair<int,int> query(int k, int s, int e, int a, int b){
		if(s>=b||e<=a)return mp(1<<20,-1); // operation neutral
		push(k,s,e);
		if(s>=a&&e<=b)return st[k];
		int m=(s+e)/2;
		return min(query(2*k,s,m,a,b),query(2*k+1,m,e,a,b)); // operation
	}
	int getseg(int k, int s, int e, int p){
		if(w[k].size())return *w[k].begin();
		int m=(s+e)/2;
		if(p<m)return getseg(2*k,s,m,p);
		return getseg(2*k+1,m,e,p);
	}
	void init(){init(1,1,n);}
	void add(int a, int b, int v){add(1,1,n,a,b,v);}
	void del(int a, int b, int v){del(1,1,n,a,b,v);}
	void asd(){asd(1,1,n);}
	int getseg(int i){return getseg(1,1,n,i);}
	pair<int,int> query(int a, int b){return query(1,1,n,a,b);}
}; // usage: STree rmq(n);rmq.init(x);rmq.upd(s,e,v);rmq.query(s,e);

#define MAXN 100005

vector<int> g[MAXN];int n;
int wg[MAXN],dad[MAXN],dep[MAXN]; // weight,father,depth
void dfs1(int x){
	wg[x]=1;
	for(int y:g[x])if(y!=dad[x]){
		dad[y]=x;dep[y]=dep[x]+1;dfs1(y);
		wg[x]+=wg[y];
	}
}
int curpos,pos[MAXN],head[MAXN];
void hld(int x, int c){
	if(c<0)c=x;
	pos[x]=curpos++;head[x]=c;
	int mx=-1;
	for(int y:g[x])if(y!=dad[x]&&(mx<0||wg[mx]<wg[y]))mx=y;
	if(mx>=0)hld(mx,c);
	for(int y:g[x])if(y!=mx&&y!=dad[x])hld(y,-1);
}
void hld_init(){dad[0]=-1;dep[0]=0;dfs1(0);curpos=0;hld(0,-1);}
void queryadd(int x, int y, int v, STree& rmq){
	while(head[x]!=head[y]){
		if(dep[head[x]]>dep[head[y]])swap(x,y);
		rmq.add(pos[head[y]],pos[y]+1,v);
		y=dad[head[y]];
	}
	if(dep[x]>dep[y])swap(x,y); // now x is lca
	rmq.add(pos[x]+1,pos[y]+1,v);
}
void querydel(int x, int y, int v, STree& rmq){
	while(head[x]!=head[y]){
		if(dep[head[x]]>dep[head[y]])swap(x,y);
		rmq.del(pos[head[y]],pos[y]+1,v);
		y=dad[head[y]];
	}
	if(dep[x]>dep[y])swap(x,y); // now x is lca
	rmq.del(pos[x]+1,pos[y]+1,v);
}
// for updating: rmq.upd(pos[x],v);

vector<pair<int,int> > q;

int main(){
	scanf("%d",&n);
	fore(i,1,n){
		int x,y;
		scanf("%d%d",&x,&y);x--;y--;
		g[x].pb(y);
		g[y].pb(x);
	}
	fore(i,1,n){
		int x,y;
		scanf("%d%d",&x,&y);x--;y--;
		q.pb(mp(x,y));
	}
	hld_init();
	STree rmq(n);
	rmq.init();
	fore(i,0,n-1)queryadd(q[i].fst,q[i].snd,i,rmq);
	fore(i,0,n-1){
		auto p=rmq.query(1,n);
		if(p.fst>1){puts("NO");return 0;}
		assert(p.fst==1);
		int x=p.snd;
		int z=rmq.getseg(x);
		querydel(q[z].fst,q[z].snd,z,rmq);
		rmq.asd();
	}
	puts("YES");
	return 0;
}

Measured memory_bytes: 114292