#include<bits/stdc++.h>
#define YES {puts("YES"),exit(0);}
#define NO {puts("NO"),exit(0);}
using namespace std;
typedef long long giant;
inline char nchar() {
	static const int bufl=1<<20;
	static char buf[bufl],*a=NULL,*b=NULL;
	return a==b && (b=(a=buf)+fread(buf,1,bufl,stdin),a==b)?EOF:*a++;
}
inline int read() {
	int x=0,f=1;
	char c=nchar();
	for (;!isdigit(c);c=nchar()) if (c=='-') f=-1;
	for (;isdigit(c);c=nchar()) x=x*10+c-'0';
	return x*f;
}
const int maxn=1e5+1;
const int INT_INF=1e8;
const giant LLONG_INF=1e17;
template<typename T> inline void Min(T &x,T y) {if (y<x) x=y;}
struct R {
	int x,y,id;
} red[maxn];
struct D {
	int cs; // times be covered
	giant ids; // sum of covered id
	D (int x=INT_INF,giant y=LLONG_INF):cs(x),ids(y) {}
	inline void operator += (D b) {cs+=b.cs,ids+=b.ids;}
	inline friend D operator + (D a,D b) {a+=b;return a;}
	inline void operator -= (D b) {cs-=b.cs,ids-=b.ids;}
	inline friend D operator - (D a,D b) {a-=b;return a;}
	inline bool operator < (const D b) const {return tie(cs,ids)<tie(b.cs,b.ids);}
	inline bool operator > (const D b) const {return tie(cs,ids)>tie(b.cs,b.ids);}
	inline bool operator == (const D b) const {return tie(cs,ids)==tie(b.cs,b.ids);}
	inline bool operator () () const {return cs || ids;}
	inline bool operator ! () const {return !cs && !ids;}
	inline void clear() {cs=0,ids=0;}
};
struct M {
	D d;
	int x;
	M () {x=INT_INF;}
	M (D a,int b):d(a),x(b) {}
	inline void operator += (D b) {d+=b;}
	inline bool operator < (const M b) const {return tie(d,x)<tie(b.d,b.x);}
	inline bool operator > (const M b) const {return tie(d,x)>tie(b.d,b.x);}
	inline bool operator == (const M b) const {return tie(d,x)==tie(b.d,b.x);}
};
int n,m;
stack<int> sta;
class tree {
private:
	struct P {
		P *ch[2],*fa;
		int x;
		M w,mi;
		P () {ch[0]=ch[1]=fa=NULL;}
		P (int x,M w):x(x),w(w) {mi=w,ch[0]=ch[1]=fa=NULL;}
	} *rt;
	inline bool rson(P *x) {return x->fa->ch[1]==x;}
	inline void update(P *x) {
		assert(x);
		x->mi=x->w;
		for (int i=0;i<2;++i) if (x->ch[i]) Min(x->mi,x->ch[i]->mi);
	}
	inline void rotate(P *x) {
		P *f=x->fa;
		int d=rson(x);
		P *c=x->ch[d^1];
		if (f->fa) f->fa->ch[rson(f)]=x;
		if (c) c->fa=f;
		x->fa=f->fa,f->fa=x,x->ch[d^1]=f,f->ch[d]=c;
		update(f),update(x);
	}
	void splay(P *x) {
		if (x==rt) return;
		while (x->fa!=rt) x->fa->fa==rt?rotate(x):(rson(x)==rson(x->fa)?(rotate(x->fa),rotate(x)):(rotate(x),rotate(x)));
	}
	P* find(int x) {
		P *r=rt;
		while (true) {
			if (r->x==x) break;
			r=r->ch[x>r->x];
		}
		assert(r);
		splay(r);
		return r;
	}
	P* getpre(P *x) {
		x=x->ch[0];
		assert(x);
		for (;x->ch[1];x=x->ch[1]);
		splay(x);
		return x;
	}
public:
	tree () {rt=new P(INT_INF,M(D(INT_INF+1,LLONG_INF+1),INT_INF));}
	void insert(int x,M w) {
		P *nw=new P(x,w),*r=rt;
		while (true) {
			P *&tmp=r->ch[x>r->x];
			if (tmp) r=tmp; else {(tmp=nw)->fa=r;break;}
		}
		splay(nw);
	}
	void erase(int x) {
		P *f=find(x);
		splay(f);
		if (!f->ch[0]) {
			rt->ch[rson(f)]=f->ch[1];
			if (f->ch[1]) f->ch[1]->fa=rt;
			update(rt);
		} else if (!f->ch[1]) {
			rt->ch[rson(f)]=f->ch[0];
			if (f->ch[0]) f->ch[0]->fa=rt;
			update(rt);
		} else {
			P *p=getpre(f);
			splay(p);
			p->ch[1]=f->ch[1];
			if (f->ch[1]) f->ch[1]->fa=p;
			update(p),update(rt);
		}
		delete f;
	}
	M query_mi() {
		update(rt);
		return rt->mi;
	}
};
namespace lct {
	const int maxp=maxn<<1;
	typedef pair<int,int> Pair;
	Pair which[maxp];
	struct node {
		int ch[2],fa,size,vs;
		bool rev;
		D tag;
		M w,chain_mi,sub_mi,cb_mi,mi; // which point it is
		tree s;
		void sub_insert(int x);
		void sub_erase(int x);
		node ():size(0),vs(0) {}
	} t[maxp];
	inline void update(int x);
	void node::sub_insert(int x) {
		s.insert(x,t[x].mi);
		sub_mi=s.query_mi();
	}
	void node::sub_erase(int x) {
		s.erase(x);
		sub_mi=s.query_mi();
	}
	int tot=maxn;
	void init() {
		for (int i=1;i<maxn;++i) {
			t[i].w.x=i;
			t[i].chain_mi=t[i].mi=t[i].w;
		}
	}
	int __initer=(init(),0);
	inline bool rson(int x) {return t[t[x].fa].ch[1]==x;}
	inline bool isroot(int x) {return t[t[x].fa].ch[rson(x)]!=x;}
	inline int newnode() {
		t[tot].tag=D(0,0);
		t[tot].w=t[tot].chain_mi=t[tot].sub_mi=t[tot].mi=M(D(0,0),tot);
		return tot++;
	}
	inline void update(int x) {
		M &cm=t[x].chain_mi=t[x].w,&bm=t[x].cb_mi=t[x].sub_mi;
		for (int i=0;i<2;++i) {
			Min(cm,t[t[x].ch[i]].chain_mi);
			Min(bm,t[t[x].ch[i]].cb_mi);
		}
		t[x].mi=min(cm,bm);
		t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].vs+1;
	}
	inline void push(int x,D d) {
		t[x].tag+=d;
		t[x].w+=d;
		t[x].chain_mi+=d;
		t[x].mi=min(t[x].chain_mi,t[x].cb_mi);
	}
	inline void doit_rev(int x) {
		if (!t[x].rev) return;
		swap(t[x].ch[0],t[x].ch[1]);
		for (int i=0;i<2;++i) if (t[x].ch[i]) t[t[x].ch[i]].rev^=true;
		t[x].rev=false;
	}
	inline void doit_tag(int x) {
		if (!t[x].tag) return;
		for (int i=0;i<2;++i) if (t[x].ch[i]) push(t[x].ch[i],t[x].tag);
		t[x].tag.clear();
	}
	inline void doit(int x) {
		doit_tag(x);
		doit_rev(x);
	}
	void down(int x) {
		if (!isroot(x)) down(t[x].fa); else if (t[x].fa) t[t[x].fa].sub_erase(x);
		doit(x);
	}
	inline void rotate(int x) {
		int f=t[x].fa,d=rson(x),c=t[x].ch[d^1];
		if (!isroot(f)) t[t[f].fa].ch[rson(f)]=x;
		if (c) t[c].fa=f;
		t[x].fa=t[f].fa,t[f].fa=x,t[x].ch[d^1]=f,t[f].ch[d]=c;
		update(f),update(x);
	}
	void splay(int x) {
		down(x);
		while (!isroot(x)) isroot(t[x].fa)?rotate(x):(rson(x)==rson(t[x].fa)?(rotate(t[x].fa),rotate(x)):(rotate(x),rotate(x)));
		if (t[x].fa) t[t[x].fa].sub_insert(x);
	}
	void access(int x) {
		for (int last=0;x;x=t[last=x].fa) {
			splay(x);
			if (last) t[x].sub_erase(last);
			if (t[x].ch[1]) t[x].sub_insert(t[x].ch[1]);
			t[x].vs-=t[last].size;
			t[x].vs+=t[t[x].ch[1]].size;
			t[x].ch[1]=last;
			update(x);
		}
	}
	inline void makeroot(int x) {
		access(x);
		splay(x);
		t[x].rev^=true;
	}
	inline int link(int x,int y) {
		makeroot(x);
		t[x].fa=y;
		t[y].sub_insert(x);
		t[y].vs+=t[x].size;
		update(y);
	}
	inline void cut(int x,int y) {
		makeroot(x);
		access(y);
		splay(y);
		assert(t[y].ch[0]==x);
		t[y].ch[0]=t[x].fa=0;
		update(y);
	}
	inline void add_edge(int x,int y) {
		int p=newnode();
		which[p]=Pair(x,y);
		link(x,p),link(y,p);
	}
	inline void red_cover(int x,int y,int id) {
		makeroot(x);
		access(y);
		splay(y);
		push(y,D(1,id));
	}
	inline void red_flash(int x,int y,int id) {
		makeroot(x);
		access(y);
		splay(y);
		push(y,D(-1,-id));
	}
	inline bool cancel(int x) {
		makeroot(x);
		if (t[x].size==1) return false;
		if (t[x].mi.d.cs!=1) NO;
		int p=t[x].mi.x,id=t[x].mi.d.ids;
		red_flash(red[id].x,red[id].y,id);
		int a=which[p].first,b=which[p].second;
		cut(a,p),cut(b,p);
		sta.push(a),sta.push(b);
		return true;
	}
}
int main() {
	n=read();
	for (int i=1;i<n;++i) {
		int x=read(),y=read();
		lct::add_edge(x,y);
	}
	for (int i=1;i<n;++i) {
		int &x=red[i].x=read(),&y=red[i].y=read();
		lct::red_cover(x,y,i);
	}
	m=n-1;
	sta.push(1);
	while (!sta.empty()) {
		int x=sta.top();
		sta.pop();
		m-=lct::cancel(x);
	}
	puts(m?"NO":"YES");
	return 0;
}


Measured memory_bytes: 66432