#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;

bool deada[100100], deadb[100100];

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) {
        mr.erase(mr.find(ar[i]));
        //printf("update %d %d, as %d changes to %d\n", ar[i].first, ar[i].second, x, y);
        ar[i].first = mycomp[ar[i].first], ar[i].second = mycomp[ar[i].second];

        fix(ar[i]);

        insert(mr, mb, ar[i]);
}

void updb (int i) {
        mb.erase(mb.find(ab[i]));
        ab[i].first = mycomp[ab[i].first], ab[i].second = mycomp[ab[i].second];

        fix(ab[i]);

        insert(mb, mr, ab[i]);
}

void merge (int a, int b) {

        int oa = a, ob = 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 (!deada[i]) {
                if (ar[i].first == oa && ar[i].second == ob) {
                        deada[i] = true;
                        continue;
                }
                assert(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);
                c[a].r.PB(i);
        }
        c[b].r.clear();

        //merge blues
        for (int i : c[b].b) if (!deadb[i]) {
                if (ab[i].first == oa && ab[i].second == ob) {
                        deadb[i] = true;
                        continue;
                }
                assert(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);
                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: 30464