#include <bits/stdc++.h>
using namespace std;
#define fo(i,a,b) for(int i=(a);i<(b);i++)
#define MOD 1000000007
#define MP make_pair
#define PB push_back
typedef long long ll;
 
int N, mycomp[100100];
pair<int, int> ar[100100], ab[100100];
set<pair<int, int>> mr, mb;
//set of reds, set of blues, if they correspond, then you can delete both and merge comp
queue<pair<int, int>> q;
 
struct comp {
        vector<int> nodes, r, b;
} c[100100];
 
void fix (pair<int,int>& a) {
        if (a.first > a.second) swap(a.first, a.second);
}
 
void insert (set<pair<int,int>>& into, set<pair<int,int>>& opp, pair<int,int> val) {
        //handles an insertion, makes sure no duplicates, and then checks opposite for match
        if (into.insert(val).second == false) {
                puts("NO");
                exit(0);
        }
        //printf("inserting %d %d\n", val.first, val.second);
        if (opp.find(val) != opp.end()) {
                //printf("q push %d %d\n", val.first, val.second);
                q.push(val);
        }
}
 
void updr (int i, int x, int y) {
        mr.erase(mr.find(ar[i]));
        //printf("update %d %d, as %d changes to %d\n", ar[i].first, ar[i].second, x, y);
        if (ar[i].first == x) {
                ar[i].first = y;
        } else {
                assert(ar[i].second == x);
                ar[i].second = y;
        }
        fix(ar[i]);
 
        insert(mr, mb, ar[i]);
}
 
void updb (int i, int x, int y) {
        mb.erase(mb.find(ab[i]));
        if (ab[i].first == x) {
                ab[i].first = y;
        } else {
                assert(ab[i].second == x);
                ab[i].second = y;
        }
        fix(ab[i]);
 
        insert(mb, mr, ab[i]);
}
 
void merge (int a, int b) {
        //printf("merge %d %d\n", a, b);
        //for (int i : c[b].r) printf("%d has reds %d\n", b, i);
        //for (int i : c[b].b) printf("%d has blue %d\n", b, i);
 
        //merging based on r + b size
        int sza = (int) c[a].nodes.size() + (int) c[a].r.size() + (int) c[a].b.size();
        int szb = (int) c[b].nodes.size() + (int) c[b].r.size() + (int) c[b].b.size();
        if (sza < szb) swap(a, b);
 
        //merge nodes
        for (int i : c[b].nodes) {
                c[a].nodes.PB(i);
                mycomp[i] = a;
        }
        c[b].nodes.clear();
 
        //merge reds
        for (int i : c[b].r) if (mycomp[ar[i].first] != mycomp[ar[i].second]) {
                //printf("red merge from comp %d to comp %d - %d %d\n", b, a, ar[i].first, ar[i].second);
                updr(i, b, a);
                c[a].r.PB(i);
        }
        c[b].r.clear();
 
        //merge blues
        for (int i : c[b].b) if (mycomp[ab[i].first] != mycomp[ab[i].second]) {
                //printf("blue merge from comp %d to comp %d - %d %d\n", b, a, ab[i].first, ab[i].second);
                updb(i, b, a);
                c[a].b.PB(i);
        }
        c[b].b.clear();
}
 
int main () {
        scanf("%d", &N);
        fo(i, 1, N) {
                int a, b;
                scanf("%d %d", &a, &b);
                c[a].b.PB(i), c[b].b.PB(i);
 
                ab[i] = MP(a, b), fix(ab[i]);
                insert(mb, mr, ab[i]);
        }
        fo(i, 1, N) {
                int a, b;
                scanf("%d %d", &a, &b);
                c[a].r.PB(i), c[b].r.PB(i);
 
                ar[i] = MP(a, b), fix(ar[i]);
                insert(mr, mb, ar[i]);
        }
        fo(i, 1, N+1) {
                mycomp[i] = i;
                c[i].nodes.PB(i);
        }
 
        while (q.size()) {
                int a, b; tie(a,b) = q.front(), q.pop();
                a = mycomp[a], b = mycomp[b];
                if (a>b) swap(a, b);
 
                //printf("onq %d %d\n", a, b);
 
                //sometimes i may end up pushing twice
                if (a == b) continue;
 
                //for (auto i : mr) printf("mr has %d %d\n", i.first, i.second);
                //for (auto i : mb) printf("mb has %d %d\n", i.first, i.second);
 
                mr.erase(MP(a, b));
                mb.erase(MP(a, b));
 
                //puts("after direct erasal");
                //for (auto i : mr) printf("mr has %d %d\n", i.first, i.second);
                //for (auto i : mb) printf("mb has %d %d\n", i.first, i.second);
 
                merge(a, b);
 
                //puts("after merge touchup");
                //for (auto i : mr) printf("mr has %d %d\n", i.first, i.second);
                //for (auto i : mb) printf("mb has %d %d\n", i.first, i.second);
        }
 
        fo(i, 2, N+1) if (mycomp[i] != mycomp[i-1]) {
                puts("NO");
                return 0;
        }
 
        puts("YES");
 
        return 0;
}

Measured memory_bytes: 30332