// luogu-judger-enable-o2
/*#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
 
#define boost ios_base :: sync_with_stdio(), cin.tie(0), cout.tie(0)
#define pb push_back

typedef long long LL;
using namespace std;
 
void read(int &v){int k=0,l=1;char ch;ch=getchar();while (ch>'9' || ch<'0'){if (ch=='-') l=-1;ch=getchar();}while (ch>='0' && ch<='9') k=k*10+ch-'0',ch=getchar();v=l*k;}
void print(int v){if (v<0) putchar('-'),v=-v;if (v>9) print(v/10);putchar(v%10+'0');}
int max(int a, int b) { return a>b ? a: b;}
int min(int a, int b) { return a<b ? a: b;}

static const int MAXN = 2e5 + 5;
static int n, tot, m, root, mod;
static int id[MAXN << 1], son[MAXN << 1], size[MAXN << 1], w[MAXN << 1];
static int wt[MAXN << 1], fa[MAXN << 1], top[MAXN << 1], dep[MAXN << 1];
static int tree[MAXN << 2], lazy[MAXN << 2];

// vector<int > v[MAXN];

void build(int l, int r, int p) {
        if (l == r) {
                tree[p] = wt[l];
                // tree[p] %= mod;
                //if (tree[p] > mod) tree[p] -= mod;
                return;
        }
        int mid = (l + r) >> 1;
        build(l, mid, p << 1);
        build(mid + 1, r, p << 1 | 1);
        tree[p] = min(tree[p << 1], tree[p << 1 | 1]);
        // tree[p] = (tree[p << 1] + tree[p << 1 | 1]) % mod;
}

// void pushdown(int l, int r, int p) {
//         if (lazy[p]) {
//                 int mid = (l + r) >> 1;
//                 lazy[p << 1] += lazy[p];
//                 lazy[p << 1 | 1] += lazy[p];
//                 tree[p << 1] += (mid - l + 1) * lazy[p];
//                 tree[p << 1 | 1] += (r - mid) * lazy[p];
//                 tree[p << 1] %= mod;
//                 tree[p << 1 | 1] %= mod;
//                 lazy[p] = 0;
//         }
// }

void maintain(int l, int r, int p, int st, int ed, int v) {
        if (st <=l && ed >= r) {
                tree[p] += (r - l + 1) * v;
                lazy[p] += v;
                return;
        }
        pushdown(l, r, p);
        int mid = (l + r) >> 1;
        if (ed <= mid) maintain(l, mid, p << 1, st, ed, v);
                        else if (st > mid) maintain(mid + 1, r, p << 1 | 1, st, ed, v);
                                        else maintain(l, mid, p << 1, st, ed, v) , maintain(mid + 1, r, p << 1 | 1, st, ed, v);
        tree[p] = (tree[p << 1] + tree[p << 1 | 1]) % mod;
}

int query(int l, int r, int p, int st, int ed) {
        if (st <= l && ed >= r) {
                return tree[p] % mod;
        }
        pushdown(l, r, p);
        int mid = (l + r) >> 1;
        if (ed <= mid) return query(l, mid, p << 1, st, ed) % mod;
                else if (st > mid) return query(mid + 1, r, p << 1 | 1, st, ed) % mod;
                        else return (query(l, mid, p << 1, st, ed) + query(mid + 1, r, p << 1 | 1, st, ed)) % mod;
        tree[p] = (tree[p << 1] + tree[p << 1 | 1]) % mod;
}

void dfs1(int x, int pre, int deep) {
        dep[x] = deep;
        fa[x] = pre;
        size[x] = 1;
        int maxson = -1;
        for (int i=0; i<v[x].size(); ++i ) {
                int vet = v[x][i];
                if (vet == pre) continue;
                dfs1(vet, x, deep + 1);
                size[x] += size[vet];
                if (size[vet] > maxson) {
                        maxson = size[vet];
                        son[x] = vet;
                }
        }
}

void dfs2(int x, int pre) {
        id[x] = ++tot;
        wt[tot] = w[x];
        top[x] = pre;
        if (!son[x]) return;
        dfs2(son[x], pre);
        for (int i=0; i<v[x].size(); ++i ) {
                int vet = v[x][i];
                if (fa[x] == vet || vet == son[x]) continue;
                dfs2(vet, vet);
        }
}

int main() {
        // boost;
        read(n);
        for (int i = 1; i , n; ++i ) {
                read(x), read(y);
                add(x, y);
                add(y, x);
        }
        dfs1(1, 0);
        dfs(1, 0, 1);
        return 0;
}
*/
#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
 
#define boost ios_base :: sync_with_stdio(), cin.tie(0), cout.tie(0)
#define pb push_back

typedef long long LL;
using namespace std;
 
void read(int &v){int k=0,l=1;char ch;ch=getchar();while (ch>'9' || ch<'0'){if (ch=='-') l=-1;ch=getchar();}while (ch>='0' && ch<='9') k=k*10+ch-'0',ch=getchar();v=l*k;}
void print(int v){if (v<0) putchar('-'),v=-v;if (v>9) print(v/10);putchar(v%10+'0');}
int max(int a, int b) { return a>b ? a: b;}
int min(int a, int b) { return a<b ? a: b;}

static const int MAXN = 1e5 + 5;

static int n, fa[MAXN];
set<int> s1[MAXN];
set<int> s2[MAXN];
queue< pair< int , int > > q;

int get_fa(int x) {
        return (fa[x] == x) ? x : (fa[x] = get_fa(fa[x]));
}

int main() {
        // boost;
        // freopen("B.in", "r", stdin);
        // freopen("B.out", "w", stdout);
        read(n);
        for (int i = 1; i <= n; ++i ) {
                fa[i] = i;
        }
        for (int i = 1; i < n; ++i ) {
                int x, y;
                read(x), read(y);
                s1[x].insert(y);
                s1[y].insert(x);
        }
        for (int i = 1; i < n; ++i ) {
                int x, y;
                read(x), read(y);
                s2[x].insert(y);
                s2[y].insert(x);
                if (s1[x].find(y) != s1[x].end())
                        q.push(make_pair(x, y));
        }
        while (!q.empty()) {
                int x = q.front().first;
                int y = q.front().second;
                q.pop();
                int tx = get_fa(x);
                int ty = get_fa(y);
                if (tx == ty) continue;
                if (s1[tx].size() + s2[tx].size() > s1[ty].size() + s2[ty].size()) 
                        swap(tx, ty);
                fa[tx] = ty;
                s1[tx].erase(ty);
                s1[ty].erase(tx);
                s2[tx].erase(ty);
                s2[ty].erase(tx);
                for (set<int> :: iterator it = s1[tx].begin(); it != s1[tx].end(); ++it ) {
                        int now = *it;
                        s1[now].erase(tx);
                        s1[now].insert(ty);
                        s1[ty].insert(now);
                        if (s2[now].find(ty) != s2[now].end())
                                q.push(make_pair(now, ty));
                }
                for (set<int> :: iterator it = s2[tx].begin(); it != s2[tx].end(); ++it ) {
                        int now = *it;
                        s2[now].erase(tx);
                        s2[now].insert(ty);
                        s2[ty].insert(now);
                        if (s1[now].find(ty) != s1[now].end())
                                q.push(make_pair(now, ty));
                }
        }
        int ans = 0;
        for (int i = 1; i <= n; ++i )
                if (get_fa(i) == i) ans ++;
        (ans == 1) ? puts("YES") : puts("NO");
        return 0;
}
/*
5 
1 2 
2 3 
3 4 
4 5 
3 4 
2 4 
1 4 
1 5

6 
1 2 
3 5
4 6 
1 6 
5 1 
5 3 
1 4 
2 6 
4 3 
5 6
*/

Measured memory_bytes: 29056