#include <bits/stdc++.h>

const int MAXN = 200010;
const int mod = 1000000007;
typedef long long LL;
void reduce(int & x) { x += x >> 31 & mod; }
int mul(int a, int b) { return (LL) a * b % mod; }
int pow(int a, int b, int res = 1) {
	for (; b; b >>= 1, a = mul(a, a)) if (b & 1) res = mul(res, a);
	return res;
}
int remod(LL x) { x %= mod; return x + (x >> 63 & mod); }
int head[MAXN], nxt[MAXN << 1], to[MAXN << 1], tot;
void addedge(int b, int e) {
	nxt[++tot] = head[b]; to[head[b] = tot] = e;
	nxt[++tot] = head[e]; to[head[e] = tot] = b;
}
int xs[MAXN], ys[MAXN], bak, fa[MAXN], hav[MAXN];
int n;
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
int li[MAXN], cnt, cir[MAXN];
int ex[MAXN], ey[MAXN], et[MAXN], idx;
std::map<int, int> M[MAXN];
bool dfs(int u, int S, int fa = 0) {
	li[++cnt] = u;
	if (u == S) return true;
	for (int i = head[u]; i; i = nxt[i])
		if (to[i] != fa)
			if (dfs(to[i], S, u)) return true;
	--cnt;
	return false;
}
void append(int x, int y) {
	ex[++idx] = std::min(x, y);
	ey[idx] = std::max(x, y) - n;
	et[idx] = y > x;
}
void dfs2(int u, int fa = 0) {
	for (int i = head[u]; i; i = nxt[i])
		if (!cir[to[i]] && to[i] != fa)
			append(u, to[i]), dfs2(to[i], u);
}
int fac[MAXN], inv[MAXN];
typedef std::vector<int> VI;
VI out[MAXN], lx[MAXN];
int ind[MAXN], sz[MAXN], rk[MAXN];
int dfs3(int u) {
	sz[u] = 1; int res = 1;
	for (auto t : out[u])
		res = mul(res, dfs3(t)), sz[u] += sz[t];
	return mul(res, inv[sz[u]]);
}
void adde(int b, int e) { ++ind[e]; out[b].push_back(e); }
int solve() {
	for (int i = 1; i <= idx; ++i) out[i].clear(), ind[rk[i] = i] = 0;
	std::sort(rk + 1, rk + 1 + idx, [] (int a, int b) { return ey[a] < ey[b]; });
	for (int i = 1; i <= idx; ++i) lx[ex[i]].clear();
	for (int i = 1; i <= idx; ++i) {
		int u = rk[i];
		if (et[u] == 0) {
			for (auto t : lx[ex[u]]) adde(u, t);
			lx[ex[u]].clear();
		}
		lx[ex[u]].push_back(u);
	}
	std::sort(rk + 1, rk + 1 + idx, [] (int a, int b) { return ex[a] < ex[b]; });
	for (int i = 1; i <= idx; ++i) lx[ey[i]].clear();
	for (int i = 1; i <= idx; ++i) {
		int u = rk[i];
		if (et[u] == 1) {
			for (auto t : lx[ey[u]]) adde(u, t);
			lx[ey[u]].clear();
		}
		lx[ey[u]].push_back(u);
	}
	int res = 1, tz = 0;
	for (int i = 1; i <= idx; ++i) if (ind[i] == 0) {
		res = mul(res, dfs3(i)); tz += sz[i];
	}
	return res;
}
int main() {
	std::ios_base::sync_with_stdio(false), std::cin.tie(0);
	fac[0] = fac[1] = inv[0] = inv[1] = 1;
	for (int i = 2; i != MAXN; ++i) {
		fac[i] = mul(fac[i - 1], i);
		inv[i] = mul(inv[mod % i], mod - mod / i);
	}
	std::cin >> n;
	for (int i = 1; i <= n * 2; ++i) fa[i] = i, hav[i] = 1;
	for (int i = 1, a, b; i <= n * 2; ++i) {
		std::cin >> a >> b;
		int _a = a, _b = b + n;
		a = find(a), b = find(b + n);
		if (a == b) xs[++bak] = _a, ys[bak] = _b;
		else addedge(_a, _b);
		if (b != a) hav[a] += hav[b]; fa[b] = a; --hav[a];
	}
	for (int i = 1; i <= n; ++i) if (i == fa[i])
		if (hav[i]) return std::cout << 0 << std::endl, 0;
	int ans = 1;
	for (int i = 1; i <= bak; ++i) {
		cnt = idx = 0;
		dfs(xs[i], ys[i]);
		for (int j = 1; j <= cnt; ++j) cir[li[j]] = true;
		li[0] = li[cnt];
		for (int j = 0; j < cnt; ++j) append(li[j], li[j + 1]);
		for (int j = 1; j <= cnt; ++j) dfs2(li[j]);
		int t = solve();
		for (int j = 1; j <= cnt; ++j) et[j] ^= 1;
		reduce(t += solve() - mod);
		ans = mul(ans, t);
	}
	std::cout << mul(ans, fac[n * 2]) << std::endl;
	return 0;
}


Measured memory_bytes: 41984