#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define N 101000
#define NN 401000
template<typename T> inline void read(T &x) {
	x = 0; char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); }
}
using namespace std;
int n;
struct edge{
	int nxt, to;
}e[N << 1];
int head[N], ecnt;
inline void addedge(int from, int to) {
	e[++ecnt] = (edge){head[from], to};
	head[from] = ecnt;
}

int son[N], siz[N], dep[N], fa[N];
void dfs_son(int cur, int faa) {
	fa[cur] = faa, siz[cur] = 1, dep[cur] = dep[faa] + 1;
	int mx = 0;
	for (int i = head[cur]; i; i = e[i].nxt) {
		int to = e[i].to; if (to == faa)	continue;
		dfs_son(to, cur); siz[cur] += siz[to];
		if (siz[to] > mx)	mx = siz[to], son[cur] = to;
	}
}
int top[N], dfn[N], dcnt;
void dfs_chain(int cur, int topp) {
	top[cur] = topp, dfn[cur] = ++dcnt;
	if (son[cur])	dfs_chain(son[cur], topp);
	for (int i= head[cur]; i; i = e[i].nxt) {
		int to = e[i].to; if (to == fa[cur] || to == son[cur])	continue;
		dfs_chain(to, to);
	}
}

int U[N], V[N];
int taga[NN], tagx[NN], mn[NN], mnpos[NN];
int ls[NN], rs[NN], ttot, root;
void build(int L, int R, int &cur) {
	cur = ++ttot;
	mnpos[cur] = L;
	if (L == R)	return ;
	int mid = (L + R) >> 1;
	build(L, mid, ls[cur]), build(mid + 1, R, rs[cur]);
}
inline void pushup(int cur) {
	if (mn[ls[cur]] < mn[rs[cur]])	mn[cur] = mn[ls[cur]], mnpos[cur] = mnpos[ls[cur]];
	else	mn[cur] = mn[rs[cur]], mnpos[cur] = mnpos[rs[cur]];
}
inline void pushadd(int cur, int x) {
	if (!cur)	return ;
	mn[cur] += x; taga[cur] += x;
}
inline void pushxor(int cur, int x) {
	if (!cur)	return ;
	tagx[cur] ^= x;
}
inline void pushdown(int cur) {
	if (taga[cur])	pushadd(ls[cur], taga[cur]), pushadd(rs[cur], taga[cur]), taga[cur] = 0;
	if (tagx[cur])	pushxor(ls[cur], tagx[cur]), pushxor(rs[cur], tagx[cur]), tagx[cur] = 0;
}
void add(int L, int R, int l, int r, int x, int cur) {
	if (!R)	exit(0);
	if (l <= L && R <= r) {
		taga[cur] += x; mn[cur] += x; return ;
	}
	pushdown(cur);
	int mid = (L + R) >> 1;
	if (l <= mid)	add(L, mid, l, r, x, ls[cur]);
	if (r > mid)	add(mid + 1, R, l, r, x, rs[cur]);
	pushup(cur);
}
void Xor(int L, int R, int l, int r, int x, int cur) {
	if (l <= L && R <= r) {
		pushxor(cur, x);
		return ;
	}
	pushdown(cur);
	int mid = (L + R) >> 1;
	if (l <= mid)	Xor(L, mid, l, r, x, ls[cur]);
	if (r > mid)	Xor(mid + 1, R, l, r, x, rs[cur]);
	pushup(cur);
}
int query(int L, int R, int pos, int cur) {
	if (L == R)	return tagx[cur];
	pushdown(cur);
	int mid = (L + R) >> 1;
	if (pos <= mid)	return query(L, mid, pos, ls[cur]);
	return query(mid + 1, R, pos, rs[cur]);
}

inline void Add(int x, int y, int id, int type) {
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]])	swap(x, y);
		add(1, n, dfn[top[x]], dfn[x], type, root);
		Xor(1, n, dfn[top[x]], dfn[x], id, root);
		x = fa[top[x]];
	}
	if (x == y)	return ;
	if (dep[x] > dep[y])	swap(x, y);
	add(1, n, dfn[x] + 1, dfn[y], type, root);
	Xor(1, n, dfn[x] + 1, dfn[y], id, root);
}

int main() {
	read(n);
	for (int i = 1; i < n; ++i) {
		int u, v; read(u), read(v);
		addedge(u, v), addedge(v, u);
	}
	dfs_son(1, 0), dfs_chain(1, 1);
	build(1, n, root);
	for (int i = 1; i < n; ++i) {
		int u, v; read(u), read(v);
		U[i] = u, V[i] = v;
		Add(u, v, i, 1);
	}
	add(1, n, 1, 1, 1000000, root);
	int ct = 0;
	while (ct < n - 1) {
		if (mn[root] != 1) {
			puts("NO");
			return 0;
		}
		int p = mnpos[root];
		int id = query(1, n, p, root);
		add(1, n, p, p, 1000000, root);
		++ct;
		Add(U[id], V[id], id, -1);
	}
	puts("YES");
	return 0;
}


Measured memory_bytes: 18424