#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

#define SZ(v) ((int)(v.size()))
#define stime tmp1

const int N = 1e5 + 7;
const int SS = 4 * N;
const int LG = 20;
const int INF = 1e9 + 7;

int u[N], v[N];

int par[N][LG];
int stime[N], tim;
int pos[N];
int root[N];
int cnt[N];
vector<int> adj[N];
int n;
int d[N];

set<int> st[SS];
pair<int, int> seg[SS];

pair<int, int> operator + (pair<int, int> a, int b)
{
	return {a.first + b, a.second};
}

bool cmp(int v, int u)
{
	return cnt[v] > cnt[u];
}

void pre_dfs(int v, int p)
{
	for (int i=0; i<SZ(adj[v]); i++)
		if (adj[v][i] == p)
		{
			adj[v].erase(adj[v].begin() + i);
			break;
		}
	cnt[v] = 1;
	for (auto u : adj[v])
	{
		d[u] = d[v] + 1;
		par[u][0] = v;
		for (int i=1; i<LG; i++)
			par[u][i] = par[par[u][i-1]][i-1];
		pre_dfs(u, v);
		cnt[v] += cnt[u];
	}
	sort(adj[v].begin(), adj[v].end(), cmp);
}

void root_dfs(int v)
{
	stime[v] = tim++;
	for (int i=0; i<SZ(adj[v]); i++)
	{
		int u = adj[v][i];
		if (i == 0)
			root[u] = root[v];
		else
			root[u] = u;
		root_dfs(u);
	}
}

int get_parent(int v, int a)
{
	for (int i=0; i<LG; i++)
		if ((a >> i) & 1)
			v = par[v][i];
	return v;
}
int lca(int v, int u)
{
	if (d[u] > d[v])
		swap(u, v);
	v = get_parent(v, d[v] - d[u]);
	if (v == u)
		return v;
	for (int i=LG-1; i>=0; i--)
		if (par[v][i] != par[u][i])
			v = par[v][i], u = par[u][i];
	return par[v][0];
}

void modify(int l, int r, int x, int type, int s = 0, int e = n, int v = 1)
{
	if (l >= e || r <= s)
		return;
	if (l <= s && e <= r)
	{
		if (type == 0)
			st[v].insert(x);
		else if (type == 1)
			st[v].erase(x);
		else 
			seg[v].first = x;
		return;
	}
	int mid = (s + e) / 2;
	modify(l, r, x, type, s, mid, 2 * v);
	modify(l, r, x, type, mid, e, 2 * v + 1);
	seg[v] = min(seg[2 * v] + SZ(st[2 * v]), seg[2 * v + 1] + SZ(st[2 * v + 1]));
}

void build(int s = 0, int e = n, int v = 1)
{
	seg[v] = {0, s};
	if (e - s < 2)
		return;
	int mid = (s + e) / 2;
	build(s, mid, 2 * v);
	build(mid, e, 2 * v + 1);
}

int get(int ind, int s = 0, int e = n, int v = 1)
{
	if (ind >= e || ind < s)
		return -1;
	if (!st[v].empty())
		return *st[v].begin();
	if (e - s < 2)
		return -1;
	int mid = (s + e) / 2;
	int res = -1;
	res = max(res, get(ind, s, mid, 2 * v));
	res = max(res, get(ind, mid, e, 2 * v + 1));
	return res;
}

void doJob(int v, int D, int x, int type)
{
	while (D > 0)
	{
		int u = root[v];
		int need = min(D, d[v] - d[u] + 1);
		modify(stime[v] - need + 1, stime[v] + 1, x, type);
		D -= need;
		if (D > 0)
			v = par[u][0];
	}
}

int main()
{
	ios::sync_with_stdio(false);

	cin >> n;
	for (int i=1; i<n; i++)
	{
		int u, v;
		cin >> u >> v;
		u--, v--;
		adj[v].push_back(u);
		adj[u].push_back(v);
	}
	pre_dfs(0, -1);
	root_dfs(0);
	for (int i=0; i<n; i++)
		pos[stime[i]] = i;
	build();
	for (int i=1; i<n; i++)	
	{
		cin >> u[i] >> v[i];
		u[i]--, v[i]--;
		int w = lca(u[i], v[i]);
		doJob(u[i], d[u[i]] - d[w], i, 0);
		doJob(v[i], d[v[i]] - d[w], i, 0);
	}
	doJob(0, 1, INF, 2);
	for (int i=1; i<n; i++)
	{
		auto best = seg[1] + SZ(st[1]);
		int now = pos[best.second];
		//cout << best.first << " " << best.second << " " << pos[best.second] << "\n";
		if (best.first > 1)
		{
			cout << "NO\n";
			return 0;
		}
		if (best.first == 1)
		{
			int ind = get(stime[now]);
			int w = lca(u[ind], v[ind]);
			doJob(u[ind], d[u[ind]] - d[w], ind, 1);
			doJob(v[ind], d[v[ind]] - d[w], ind, 1);
		}
		doJob(now, 1, INF, 2);
	}
	cout << "YES\n";

	return 0;
}

Measured memory_bytes: 141184