#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>

using namespace std;

const int MAXN = 200000 + 1000;
const int MOD = 1000000000 + 7;

int fpow(int x, int p)
{
	int ret = 1;
	for(; p; p >>= 1, x = (long long)x * x % MOD)
		if(p & 1)
			ret = (long long)ret * x % MOD;
	return ret;
}
int inv(int x)
{
	return fpow(x, MOD - 2);
}

int fac[MAXN], fac_inv[MAXN];
void init()
{
	fac[0] = 1;
	for(int i = 1; i < MAXN; i++)
		fac[i] = (long long)fac[i - 1] * i % MOD;
	fac_inv[MAXN - 1] = inv(fac[MAXN - 1]);
	for(int i = MAXN - 2; i >= 0; i--)
		fac_inv[i] = (long long)fac_inv[i + 1] * (i + 1) % MOD;
	// cerr << fac_inv[0] << endl;
}

int n, ans = 1;
vector<int> edg[MAXN], topo[MAXN];
bool vis[MAXN], onc[MAXN];
int deg[MAXN], from[MAXN], f[MAXN], sz[MAXN];
vector<int> vp, vc;

void find_all(int x)
{
	vis[x] = true, vp.push_back(x);
	for(int i = 0; i < edg[x].size(); i++)
		if(!vis[edg[x][i]])
			find_all(edg[x][i]);
}

int find_cir(int x, int fa)
{
	// cerr << x << endl;
	static int vis[MAXN];
	vis[x] = true;
	for(int i = 0; i < edg[x].size(); i++)
		if(edg[x][i] != fa)
		{
			int y = edg[x][i], t = vis[y] ? y : find_cir(y, x);
			if(t)
			{
				onc[x] = true, vc.push_back(x);
				return t == x ? 0 : t;
			}
		}
	return 0;
}

void get_from(int x, int fa)
{
	for(int i = 0; i < edg[x].size(); i++)
		if(edg[x][i] != fa && !onc[edg[x][i]])
		{
			int y = edg[x][i];
			from[y] = x;
			get_from(y, x);
		}
}

int dp(int x)
{
	f[x] = 1, sz[x] = 1;
	for(int i = 0; i < topo[x].size(); i++)
	{
		int y = topo[x][i];
		dp(y);
		f[x] = (long long)f[x] * f[y] % MOD * fac_inv[sz[y]] % MOD;
		sz[x] += sz[y];
	}
	f[x] = (long long)f[x] * fac[sz[x] - 1] % MOD;
	return f[x];
}

int calc()
{
	// cerr << "calc : " << endl;
	int ret = 1;
	for(int i = 0; i < vp.size(); i++)
		topo[vp[i]].clear(), deg[vp[i]] = 0;
	for(int i = 0; i < vp.size(); i++)
	{
		int x = vp[i];
		for(int j = 0; j < edg[x].size(); j++)
			if(edg[x][j] < from[x])
			{
				int y = edg[x][j];
				topo[x].push_back(y), deg[y]++;
				// cerr << x << ' ' << y << endl;
			}
	}
	for(int i = 0; i < vp.size(); i++)
		if(deg[vp[i]] == 0)
		{
			int tmp = (long long)dp(vp[i]) * fac_inv[sz[vp[i]]] % MOD;
			// cout << vp[i] << ' ' << sz[vp[i]] << ' ' << tmp << endl;
			ret = (long long)ret * tmp % MOD;
		}
	return ret;
}

void solve()
{
	// cerr << vp.size() << endl;
	int edg_cnt = 0;
	for(int i = 0; i < vp.size(); i++)
		edg_cnt += edg[vp[i]].size();
	if(edg_cnt != vp.size() * 2)
	{
		ans = 0;
		return ;
	}
	vc.clear();
	find_cir(vp[0], 0);
	// cerr << vp[0] << ' ' << vc.size() << endl;
	int ret = 0;
	for(int i = 0; i < vc.size(); i++)
		get_from(vc[i], 0);
	for(int i = 0; i < vc.size(); i++)
		from[vc[i]] = vc[(i + 1) % vc.size()];
	ret = (ret + calc()) % MOD;
	for(int i = 0; i < vc.size(); i++)
		from[vc[i]] = vc[(i + vc.size() - 1) % vc.size()];
	ret = (ret + calc()) % MOD;
	ans = (long long)ans * ret % MOD;
}

int main()
{
	ios::sync_with_stdio(false);
	// freopen("1.in", "r", stdin);
	// freopen("1.out", "w", stdout);

	init();
	cin >> n;
	for(int i = 1; i <= 2 * n; i++)
	{
		int x, y;
		cin >> x >> y;
		edg[x].push_back(n + y), edg[n + y].push_back(x);
	}
	for(int i = 1; i <= 2 * n; i++)
		if(!vis[i])
		{
			vp.clear();
			find_all(i);
			solve();
		}
	ans = (long long)ans * fac[2 * n] % MOD;
	cout << ans << endl;


	return 0;
}


Measured memory_bytes: 28152