#include <bits/stdc++.h>
#define ll long long
#define mk make_pair
using namespace std;
const int N = 2e5 + 5;
const int mod = 1e9 + 7;
int n, root, root1, tag[N], deg[N], size[N];
ll ans = 1, fac[N], inv[N];
vector<int> s, ss, G[N], E[N];
unordered_map<int, int> id[N];
int row[N], col[N];
vector<int> r[N], c[N];
bool vis[N];
inline ll Pow(ll a, int x) {
	ll res = 1;
	while (x) {
		if (x & 1) res = res * a % mod;
		a = a * a % mod;
		x >>= 1;
	}
	return res;
}
void dfs(int x, int f) {
	vis[x] = 1;
	s.push_back(x);
	tag[x] = tag[0];
	for (int i = 0; i < G[x].size(); i++) {
		int u = G[x][i];
		if (u == f) continue;
		if (vis[u] && tag[u] != tag[x]) continue;
		if (!vis[u]) {
			dfs(u, x);
			ss.push_back(id[x][u]);
		} else {
			if (x < u)
				ss.push_back(id[x][u]);
			root = u;
			root1 = x;
		}
	}
}
void dfs1(int x, int f, int r) {
	if (x <= n) 
		col[x] = f;
	else 
		row[x] = f;
	for (int i = 0; i < G[x].size(); i++) {
		int u = G[x][i];
		if (u == f || u == r) continue;
		dfs1(u, x, r);
	}
}
ll cal(int x) {
	size[x] = 0;
	ll res = 1;
	for (int i = 0; i < E[x].size(); i++) {
		int u = E[x][i];
		res = res * cal(u) % mod;
		res = res * inv[size[u]] % mod;
		size[x] += size[u];
	}
	res = res * fac[size[x]] % mod;
	size[x]++;
	return res;
}
ll cal() { //cout << ss.size() << "/" << s.size() << endl;
	if (ss.size() != s.size()) return 0;
	ll res = 0;
	dfs1(root, root1, root);
	E[0].clear();
	for (int i = 0; i < ss.size(); i++) {
		E[ss[i]].clear();
		deg[ss[i]] = 0;
	}
	for (int i = 0; i < s.size(); i++) {
		int x = s[i];
		if (x <= n) {
			for (int j = 0; j < c[x].size(); j++) {
				int u = c[x][j];
				if (u < col[x]) {
					E[id[x][col[x]]].push_back(id[x][u]);
					deg[id[x][u]]++;
				}
			}
		} else {
			for (int j = 0; j < r[x].size(); j++) {
				int u = r[x][j];
				if (u < row[x]) {
					E[id[x][row[x]]].push_back(id[x][u]);
					deg[id[x][u]]++;
				}
			}
		}
	}
	for (int i = 0; i < ss.size(); i++) 
		if (deg[ss[i]] == 0) E[0].push_back(ss[i]);
	res += cal(0);
	dfs1(root1, root, root1);
	E[0].clear();
	for (int i = 0; i < ss.size(); i++) {
		E[ss[i]].clear();
		deg[ss[i]] = 0;
	}
	for (int i = 0; i < s.size(); i++) {
		int x = s[i];
		if (x <= n) {
			for (int j = 0; j < c[x].size(); j++) {
				int u = c[x][j];
				if (u < col[x]) {
					E[id[x][col[x]]].push_back(id[x][u]);
					deg[id[x][u]]++;
				}
			}
		} else {
			for (int j = 0; j < r[x].size(); j++) {
				int u = r[x][j];
				if (u < row[x]) {
					E[id[x][row[x]]].push_back(id[x][u]);
					deg[id[x][u]]++;
				}
			}
		}
	}
	for (int i = 0; i < ss.size(); i++) 
		if (deg[ss[i]] == 0) E[0].push_back(ss[i]);
	res += cal(0);
	return res % mod;
}
int main() {
	fac[0] = 1;
	for (int i = 1; i < N; i++) fac[i] = fac[i - 1] * i % mod;
	inv[N - 1] = Pow(fac[N - 1], mod - 2);
	for (int i = N - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1) % mod;
	scanf("%d", &n);
	for (int i = 1; i <= 2 * n; i++) {
		int x, y;
		scanf("%d %d", &x, &y);
		G[x].push_back(y + n);
		G[y + n].push_back(x);
		id[x][y + n] = i;
		id[y + n][x] = i;
		r[y + n].push_back(x);
		c[x].push_back(y + n);
	}
	for (int i = 1; i <= n; i++) {
		sort(c[i].begin(), c[i].end());
		sort(r[i + n].begin(), r[i + n].end());
	}
	for (int i = 1; i <= 2 * n; i++) {
		if (vis[i]) continue;
		s.clear();
		ss.clear();
		++tag[0];
		dfs(i, 0);
		ans = ans * cal() % mod * inv[s.size()] % mod;
	}
	ans = ans * fac[2 * n] % mod;
	cout << ans << endl; 
}


Measured memory_bytes: 79812