#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif
//#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;
typedef long double ld;
typedef long long ll;
const int mod = (int)1e9 + 7;
int mult(int a, int b) {
    return (1LL * a * b) % mod;
}
int sum(int a, int b) {
    int s = a + b;
    if (s >= mod) s -= mod;
    return s;
}
const int maxN = 2e5 + 10;
int fact[maxN], invfact[maxN], inv[maxN];
int cnk(int a, int b) {
    if (a < b || b < 0) return 0;
    return mult(fact[a], mult(invfact[b], invfact[a - b]));
}
int n;
bool used[maxN];
int edges = 0;
vector < int > g[maxN];
void dfs(int v, vector < int >& cmp) {
    cmp.emplace_back(v);
    used[v] = true;
    for (int to : g[v]) {
        if (v < to) edges++;
        if (!used[to]) {
            dfs(to, cmp);
        }
    }
}
int deg[maxN];
bool was[maxN];
int id(int x) {
    if (x <= n) return x;
    return x - n;
}
bool in_cyc[maxN];
int edge[maxN];
vector < int > eds[maxN];
void go(int v, int p) {
    for (int to : g[v]) {
        if (to == p) continue;
        if (in_cyc[to]) continue;
        edge[to] = v;
        go(to, v);
    }
}
pair < int, int > merge(const pair < int, int >& a, const pair < int, int >& b) {
    return make_pair(mult(cnk(a.second + b.second, a.second), mult(a.first, b.first)), a.second + b.second);
}
int in_deg[maxN];
pair < int, int > calc_ans(int v) {
    pair < int, int > ans = make_pair(1, 0);
    for (int to : eds[v]) {
        ans = merge(ans, calc_ans(to));
    }
    ans.second += 1;
    return ans;
}
pair < int, int > solve(vector < int >& cmp) {
    if (edges != cmp.size()) {
        cout << 0;
        exit(0);
    }
    queue < int > q;
    for (int v : cmp) {
        if (deg[v] == 1) {
            was[v] = true;
            q.push(v);
        }
    }
    while (!q.empty()) {
        int v = q.front();
        q.pop();
        for (int to : g[v]) {
            deg[to]--;
            if (!was[to] && deg[to] == 1) {
                q.push(to);
                was[to] = true;
            }
        }
    }
    int st = -1;
    for (int v : cmp) {
        if (!was[v]) {
            st = v;
            break;
        }
    }
    assert(st != -1);
    vector < int > cyc;
    cyc.emplace_back(st);
    was[st] = true;
    while (true) {
        bool fnd = false;
        for (int to : g[cyc.back()]) {
            if (!was[to]) {
                cyc.emplace_back(to);
                was[cyc.back()] = true;
                fnd = true;
                break;
            }
        }
        if (!fnd) break;
    }
    for (int v : cyc) in_cyc[v] = true;
    int ans = 0;
    for (int i = 0; i < cyc.size(); i++) {
        go(cyc[i], -1);
    }
    for (int it = -1; it <= 1; it += 2) {
        pair < int, int > val = make_pair(1, 0);
        for (int p = 0; p < cyc.size(); p++) {
            edge[cyc[p]] = cyc[(cyc.size() + p + it) % cyc.size()];
        }
        for (int v : cmp) {
            eds[v].clear();
            in_deg[v] = 0;
        }
        for (int v : cmp) {
            for (int u : g[v]) {
                if (u < edge[v]) {
                    eds[v].emplace_back(u);
                    //means u ranshe v
                    in_deg[u]++;
                }
            }
        }
        for (int v : cmp) {
            if (in_deg[v] == 0) {
                auto f = calc_ans(v);
                val = merge(val, f);
            }
        }
        ans = sum(ans, val.first);
    }
    return make_pair(ans, cmp.size());
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
//    freopen("input.txt", "r", stdin);
    fact[1] = invfact[1] = fact[0] = invfact[0] = inv[1] = 1;
    for (int i = 2; i < maxN; i++) {
        fact[i] = mult(fact[i - 1], i);
        inv[i] = mult(inv[mod % i], mod - mod / i);
        invfact[i] = mult(invfact[i - 1], inv[i]);
    }
    cin >> n;
    for (int i = 1; i <= 2 * n; i++) {
        int x, y;
        cin >> x >> y;
        g[x].emplace_back(y + n);
        g[y + n].emplace_back(x);
        deg[x]++;
        deg[y + n]++;
    }
    pair < int, int > ans = make_pair(1, 0);
    for (int i = 1; i <= 2 * n; i++) {
        if (!used[i]) {
            vector < int > cmp;
            edges = 0;
            dfs(i, cmp);
            ans = merge(ans, solve(cmp));
        }
    }
    cout << ans.first;
    return 0;
}

Measured memory_bytes: 27512