#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long ll ;
#define rep(i, a, b) for (int i = a; i <= b; ++ i) 
const int N = 2e5 + 5, mo = 1e9 + 7 ;
using namespace std ;

bool vis[N] ;
int opt[N], d[N], sz[N], f[N], q[N] ;
int n, e, ter[N << 1], nxt[N << 1], lnk[N], fac[N], inv[N], sum_ave, sum_sz ;

void add(int x, int y) {
	ter[++ e] = y, nxt[e] = lnk[x], lnk[x] = e, ++ d[x] ;
}

int mul(int a, int b) {
	int ans = 1, w = a % mo ;
	for ( ; b; b /= 2) {
		if (b & 1) ans = (ll) ans * w % mo ;
		w = (ll) w * w % mo ;
	}
	return ans ;
}

int C(int x, int y) {
	return (ll) fac[x] * inv[y] % mo * inv[x - y] % mo ;
}

void upd(int &x, int y) {
	x = (x + y) % mo ;
}

void dfs(int p, int las, int rt) {
	bool flg = true ;
	for (int i = lnk[p] ; i; i = nxt[i]) if (ter[i] != las && ter[i] != rt) dfs(ter[i], p, rt), flg = false ;
	if (flg) {
		sz[p] = f[p] = 1 ;
		return ;
	}
	f[p] = 1, sz[p] = 0 ;
	for (int i = lnk[p] ; i; i = nxt[i]) if (ter[i] != las && ter[i] != rt) {
		int v = ter[i] ;
		if (v < las) {
			f[p] = (ll) f[p] * C(sz[p] + sz[v], sz[v]) % mo * f[v] % mo ;
			sz[p] += sz[v] ;
		} else {
			sum_ave = (ll) sum_ave * C(sum_sz + sz[v], sz[v]) % mo * f[v] % mo ;
			sum_sz += sz[v] ;
		}
	}
	++ sz[p] ;
}

void solve(int x, int &_sz, int &ret) {
	int he = 0, ta = 1, tot = 0 ; ret = 0 ;
	q[1] = x, vis[x] = false ;
	for ( ; he != ta ; ) {
		int u = q[++ he] ;
		for (int i = lnk[u] ; i; i = nxt[i]) if (vis[ter[i]]) {
			vis[ter[i]] = false ;
			q[++ ta] = ter[i] ;
		}
	}
	q[0] = ta ;
	rep(i, 1, q[0]) {
		int u = q[i] ;
		for (int j = lnk[u] ; j; j = nxt[j]) ++ tot ;
	}
	if (tot != q[0] * 2) { ret = 0 ; return ; }
	he = 0, ta = 0 ;
	rep(i, 1, q[0]) if (d[q[i]] == 1) opt[++ ta] = q[i] ;
	for ( ; he != ta ; ) {
		int u = opt[++ he] ;
		for (int i = lnk[u] ; i; i = nxt[i]) {
			int v = ter[i] ;
			-- d[v] ;
			if (!d[v]) continue ;
			if (d[v] == 1) opt[++ ta] = v ;
		}
	}
	int k = 0, tmp[5] = {0} ;
	rep(i, 1, q[0]) if (q[i] > k && d[q[i]] > 1) k = q[i] ;
	for (int i = lnk[k] ; i; i = nxt[i]) if (d[ter[i]] > 1) tmp[++ tmp[0]] = ter[i] ;
	rep(i, 1, tmp[0]) {
		sum_ave = 1, sum_sz = 0 ;
		dfs(k, tmp[i], k) ;
		sum_ave = (ll) sum_ave * C(sum_sz + sz[k], sz[k]) % mo * f[k] % mo ;
		upd(ret, sum_ave) ;
	} 
	_sz = q[0] ;
}

int main() {
	scanf("%d", &n) ;
	int x, y ;
	rep(i, 1, n * 2) {
		scanf("%d%d", &x, &y) ;
		add(x, n + y), add(n + y, x) ;
	}
	n <<= 1 ;
	fac[0] = inv[0] = 1 ;
	rep(i, 1, n) fac[i] = (ll) fac[i - 1] * i % mo ;
	inv[n] = mul(fac[n], mo - 2) ;
	for (int i = n - 1 ; i ; -- i) inv[i] = (ll) inv[i + 1] * (i + 1) % mo ;
	int ans = 1, las = 0, _sz, ret ;
	rep(i, 1, n) vis[i] = true ;
	rep(i, 1, n) if (vis[i]) {
		solve(i, _sz, ret) ;
		ans = (ll) ans * ret % mo *  C(_sz + las, _sz) % mo ;
		las += _sz ;
	}
	printf("%d\n", ans) ;
	return 0 ;
}