#include <iostream>
#include <vector>
#include <limits>
#include <algorithm>
using namespace std;
#pragma warning (disable: 4996)

class RangeAddMinSegmentTree {
private:
	unsigned size_; std::vector<pair<int, int>> dat1, dat2;
	inline void update_(unsigned a, unsigned b, pair<int, int> x, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return;
		if (a <= l && r <= b) {
			dat2[k].first += x.first;
			dat2[k].second += x.second;
			return;
		}
		update_(a, b, x, (k << 1), l, (l + r) >> 1);
		update_(a, b, x, (k << 1) + 1, (l + r) >> 1, r);
		pair<int, int> V1 = make_pair(dat1[(k << 1) + 0].first + dat2[(k << 1) + 0].first, dat1[(k << 1) + 0].second + dat2[(k << 1) + 0].second);
		pair<int, int> V2 = make_pair(dat1[(k << 1) + 1].first + dat2[(k << 1) + 1].first, dat1[(k << 1) + 1].second + dat2[(k << 1) + 1].second);
		dat1[k] = min(V1, V2);
	}
	inline pair<int, int> query_(unsigned a, unsigned b, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return make_pair(1 << 30, 1 << 30);
		if (a <= l && r <= b) return make_pair(dat1[k].first + dat2[k].first, dat1[k].second + dat2[k].second);
		pair<int, int> lc = query_(a, b, (k << 1), l, (l + r) >> 1);
		pair<int, int> rc = query_(a, b, (k << 1) + 1, (l + r) >> 1, r);
		pair<int, int> mc = min(lc, rc);
		return make_pair(mc.first + dat2[k].first, mc.second + dat2[k].second);
	}
public:
	RangeAddMinSegmentTree() : size_(0), dat1(std::vector<pair<int, int>>()), dat2(std::vector<pair<int, int>>()) {};
	RangeAddMinSegmentTree(int size__) {
		for (size_ = 1; size_ < size__; ) size_ <<= 1;
		dat1.resize(size_ << 1, make_pair(0, 0));
		dat2.resize(size_ << 1, make_pair(0, 0));
	}
	inline unsigned size() { return size_; }
	inline void add(unsigned i, pair<int, int> x) {
		update_(i, i + 1, x, 1, 0, size_);
	}
	inline void add(unsigned l, unsigned r, pair<int, int> x) {
		update_(l, r, x, 1, 0, size_);
	}
	inline pair<int, int> query(unsigned l, unsigned r) {
		return query_(l, r, 1, 0, size_);
	}
};

class BIT {
public:
	int size_ = 0;
	vector<long long> bit;

	void init(int sz) {
		size_ = sz + 2;
		bit.resize(size_ + 2, 0);
	}
	void add(int pos, long long x) {
		pos++;
		while (pos <= size_) {
			bit[pos] += x;
			pos += (pos & -pos);
		}
	}
	long long sum(int pos) {
		pos++; long long s = 0;
		while (pos >= 1) {
			s += bit[pos];
			pos -= (pos & -pos);
		}
		return s;
	}
};

// 入力
int N;
int A[1 << 17], B[1 << 17];
int C[1 << 17], D[1 << 17];

// 木の管理
int dist[1 << 17];
vector<int> X[1 << 17];

// LCA、HL 分解
int par[1 << 17][22];
int dp[1 << 17];
int heavy[1 << 17];
int order[1 << 17], cnts;
vector<int> R[1 << 17];

// セグメントツリー
BIT Z1;
RangeAddMinSegmentTree Z2;

int prevs(int pos, int x) {
	for (int i = 21; i >= 0; i--) {
		if (x >= (1 << i)) { x -= (1 << i); pos = par[pos][i]; }
	}
	return pos;
}

int lca(int u, int v) {
	if (dist[u] > dist[v]) swap(u, v);
	v = prevs(v, dist[v] - dist[u]);
	if (u == v) return u;

	for (int i = 21; i >= 0; i--) {
		if (par[u][i] == par[v][i]) continue;
		u = par[u][i];
		v = par[v][i];
	}
	return par[u][0];
}

vector<pair<int, int>> paths(int u, int v) {
	if (dist[u] < dist[v]) return vector<pair<int, int>>{};

	int cx = u; vector<pair<int, int>> Y;
	for (int i = (int)R[u].size() - 1; i >= 0; i--) {
		if (dist[R[u][i]] <= dist[v]) break;
		Y.push_back(make_pair(order[R[u][i]], order[cx]));
		cx = par[R[u][i]][0];
	}
	Y.push_back(make_pair(order[v], order[cx]));
	return Y;
}

void adds(int u, int v, int x1, int x2) {
	int w = lca(u, v);
	int w1 = prevs(u, dist[u] - dist[w] - 1);
	int w2 = prevs(v, dist[v] - dist[w] - 1);
	vector<pair<int, int>> L1; if (dist[u] > dist[w]) L1 = paths(u, w1);
	vector<pair<int, int>> L2; if (dist[v] > dist[w]) L2 = paths(v, w2);
	for (pair<int, int> i : L1) Z2.add(i.first, i.second + 1, make_pair(x1, 0));
	for (pair<int, int> i : L2) Z2.add(i.first, i.second + 1, make_pair(x1, 0));
	for (pair<int, int> i : L1) { Z1.add(i.first, x2); Z1.add(i.second + 1, -x2); }
	for (pair<int, int> i : L2) { Z1.add(i.first, x2); Z1.add(i.second + 1, -x2); }
}

void dfs1(int pos, int pre, int dep) {
	dp[pos] = 1; dist[pos] = dep;
	for (int i : X[pos]) {
		if (i == pre) continue;
		dfs1(i, pos, dep + 1);
		par[i][0] = pos;
		dp[pos] += dp[i];
	}
}

void dfs2(int pos, int pre, vector<int> imp) {
	cnts++; order[pos] = cnts;
	R[pos] = imp;
	if (heavy[pos] != -1) dfs2(heavy[pos], pos, imp);
	for (int i : X[pos]) {
		if (i == heavy[pos] || i == pre) continue;
		vector<int> imp2 = imp;
		imp2.push_back(i);
		dfs2(i, pos, imp2);
	}
}

int main() {
	// Step #1. 入力
	cin >> N;
	for (int i = 1; i <= N - 1; i++) cin >> A[i] >> B[i];
	for (int i = 1; i <= N - 1; i++) cin >> C[i] >> D[i];
	for (int i = 1; i <= N - 1; i++) {
		X[A[i]].push_back(B[i]);
		X[B[i]].push_back(A[i]);
	}

	// Step #2. 前準備
	dfs1(1, -1, 0);
	for (int i = 1; i <= N; i++) {
		pair<int, int> maxval = make_pair(-1, -1);
		for (int j : X[i]) { if (dp[i] > dp[j]) maxval = max(maxval, make_pair(dp[j], j)); }
		heavy[i] = maxval.second;
	}
	dfs2(1, -1, vector<int>{});

	// Step #3. LCA の計算
	for (int i = 1; i <= 21; i++) {
		for (int j = 1; j <= N; j++) par[j][i] = par[par[j][i - 1]][i - 1];
	}
	Z1.init(N + 2);
	Z2 = RangeAddMinSegmentTree(N + 2);
	for (int i = 1; i <= N; i++) Z2.add(i, make_pair(0, i));

	// Step #4. 初期化
	for (int i = 1; i <= N - 1; i++) adds(C[i], D[i], 1, i);
	for (int i = 1; i <= N; i++) {
		if (Z2.query(i, i + 1) == make_pair(0, i)) Z2.add(i, make_pair(1 << 28, 0));
	}

	// Step #5. 計算
	for (int i = 1; i <= N - 1; i++) {
		pair<int, int> F = Z2.query(1, N + 1);
		if (F.first != 1) {
			cout << "NO" << endl;
			return 0;
		}
		int idx = Z1.sum(F.second);
		adds(C[idx], D[idx], -1, -idx);
		Z2.add(F.second, make_pair(1 << 28, 0));
	}
	cout << "YES" << endl;
	return 0;
}

Measured memory_bytes: 45228