#include <bits/stdc++.h>

const int maxn = 2e5 + 10, mod = 1e9 + 7;

int n, cntv, cnte, ans, oth, root, fac[maxn], ifac[maxn], par[maxn], dep[maxn], siz[maxn], flag;
bool vis[maxn], on_cyc[maxn], isr[maxn][2], viss[maxn];
std::vector<int> dag[maxn][2], cur, ccur;

struct edge {
	int to, id;

	edge() {}
	edge(int to, int id): to(to), id(id) {}
};

std::vector<edge> g[maxn];

inline int pow_mod(int x, int n) {
	int y = 1;
	while(n) {
		if(n & 1) {
			y = 1ll * x * y % mod;
		}
		x = 1ll * x * x % mod;
		n >>= 1;
	}
	return y;
}

inline void prepare() {
	fac[0] = 1;
	for (int i = 1; i < maxn; ++i) {
		fac[i] = (long long) i * fac[i - 1] % mod;
	}
	ifac[maxn - 1] = pow_mod(fac[maxn - 1], mod - 2);
	for (int i = maxn - 1; i; --i) {
		ifac[i - 1] = (long long) i * ifac[i] % mod;
	}
	return;
}

inline void dfs1(int u, int p = -1, int d = 0) {
	cur.push_back(u);
	vis[u] = 1;
	par[u] = p;
	dep[u] = d;
	++cntv;
	cnte += (int) g[u].size();
	for (auto &e: g[u]) {
		int v = e.to;
		ccur.push_back(e.id);
		if(v == p) {
			continue;
		}
		if(vis[v]) {
			root = dep[u] < dep[v] ? v : u;
			oth = u + v - root;
		}
		else {
			dfs1(v, u, d + 1);
		}
	}
	return;
}

inline void dfs2(int u, int p = -1) {
	viss[u] = 1;
	par[u] = p;
	for (auto &e: g[u]) {
		int v = e.to;
		if(!viss[v]) {
			dfs2(v, u);
		}
	}
	return;
}

inline int DP(int u) {
	siz[u] = 1;
	int ret = 1;
	for (int &v: dag[u][flag]) {
		ret = (long long) DP(v) * ret % mod;
		siz[u] += siz[v];
		ret = (long long) ret * ifac[siz[v]] % mod;
	}
	return (long long) ret * fac[siz[u] - 1] % mod;
}

int main() {
	prepare();
	scanf("%d", &n);
	for (int i = 0; i < (n << 1); ++i) {
		int x, y;
		scanf("%d%d", &x, &y);
		--x;
		y += n - 1;
		g[x].push_back(edge(y, i));
		g[y].push_back(edge(x, i));
	}
	for (int i = 0; i < (n << 1); ++i) {
		isr[i][0] = isr[i][1] = 1;
	}
	ans = fac[n << 1];
	for (int i = 0; i < (n << 1); ++i) {
		if(!vis[i]) {
			ccur.clear();
			cur.clear();
			cntv = cnte = 0;
			dfs1(i);
			if((cntv << 1) != cnte) {
				puts("0");
				return 0;
			}
			for (int u = root; u != oth; u = par[u]) {
				on_cyc[u] = 1;
			}
			on_cyc[oth] = 1;
			std::sort(ccur.begin(), ccur.end());
			ccur.resize(std::unique(ccur.begin(), ccur.end()) - ccur.begin());
			
			flag = 0;
			int ban;
			for (auto &e: g[root]) {
				if(on_cyc[e.to]) {
					ban = e.id;
				}
			}
			for (int u = root; ; ) {
				for (auto &e: g[u]) {
					int v = e.to, i = e.id;
					if(on_cyc[v] && i != ban) {
						for (auto &ee: g[u]) {
							if(ee.to < v) {
								dag[i][flag].push_back(ee.id);
								isr[ee.id][flag] = 0;
							}
						}
						u = v;
						ban = i;
						break;
					}
				}
				if(u == root) {
					break;
				}
			}
			dfs2(root);
			for (int &u: cur) {
				if(!on_cyc[u]) {
					for (auto &e: g[u]) {
						int v = e.to, i = e.id;
						if(v == par[u]) {
							for (auto &ee: g[u]) {
								if(ee.to < v) {
									dag[i][flag].push_back(ee.id);
									isr[ee.id][flag] = 0;
								}
							}
							break;
						}
					}
				}
			}
			int res1 = 1;
			for (int &u: ccur) {
				if(isr[u][flag]) {
					res1 = (long long) DP(u) * res1 % mod * ifac[siz[u]] % mod;
				}
			}

			flag = 1;
			for (auto &e: g[root]) {
				if(on_cyc[e.to]) {
					ban = e.id;
					break;
				}
			}
			for (int u = root; ; ) {
				for (auto &e: g[u]) {
					int v = e.to, i = e.id;
					if(on_cyc[v] && i != ban) {
						for (auto &ee: g[u]) {
							if(ee.to < v) {
								dag[i][flag].push_back(ee.id);
								isr[ee.id][flag] = 0;
							}
						}
						u = v;
						ban = i;
						break;
					}
				}
				if(u == root) {
					break;
				}
			}
			for (int &u: cur) {
				if(!on_cyc[u]) {
					for (auto &e: g[u]) {
						int v = e.to, i = e.id;
						if(v == par[u]) {
							for (auto &ee: g[u]) {
								if(ee.to < v) {
									dag[i][flag].push_back(ee.id);
									isr[ee.id][flag] = 0;
								}
							}
							break;
						}
					}
				}
			}
			int res2 = 1;
			for (int &u: ccur) {
				if(isr[u][flag]) {
					res2 = (long long) DP(u) * res2 % mod * ifac[siz[u]] % mod;
				}
			}

			ans = (long long) (res1 + res2) * ans % mod;
		}
	}
	printf("%d\n", ans);
	return 0;
}

Measured memory_bytes: 35560