#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pp;
typedef pair<ll,ll> pll;
void read(int& x){ scanf("%d",&x); }
void read(ll& x){ scanf("%lld",&x); }
template<typename T,typename... Args>
void read(T& a,Args&... b){ read(a); read(b...); }
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define eb emplace_back
#define x first
#define y second

const int N = 100010;

int n;

vector<pp> edge[N*2];

pp d[2*N];

bool vis[2*N];
int comp[2*N], compn;
int ec;
void dfs_compo(int x){
	vis[x]=1;
	comp[compn++]=x;
	ec += edge[x].size();
	for(auto tmp:edge[x]){
		int y=tmp.x;
		if(!vis[y]) dfs_compo(y);
	}
}

map<int,vector<pp>> lx, ly;

int cyc[2*N];
int cycn;
int stk[2*N], top;
char onstk[2*N];
void dfs_cyc(int x, int p){
	vis[x]=1;
	onstk[x]=1; stk[top++]=x;
	for(auto tmp:edge[x]){
		int y=tmp.x;
		if(y == p) continue;
		if(!vis[y]) dfs_cyc(y, x);
		else if(onstk[y]){
			for(int i=top-1;;--i){
				if((cyc[cycn++] = stk[i]) == y){
					break;
				}
			}
		}
	}
	onstk[x]=0; --top;
}

int deg[2*N];
int asgn[2*N];
const ll mod = int(1e9) + 7;
int par[2*N];
vector<int> child[2*N];

char ins[2*N];

ll fact[2*N]={1};
ll finv[2*N]={1};
ll Pow(ll b, ll e){
	if(e<0) e=(-e)*(mod-2)%mod;
	ll ret=1;
	while(e){
		if(e&1) (ret*=b)%=mod;
		(b*=b)%=mod; e>>=1;
	}
	return ret;
}
ll Comb(ll n, ll r){ return fact[n]*finv[r]%mod*finv[n-r]%mod; }

pair<ll,ll> dp(int x){
	ll cnt = 0, way = 1;
	for(int y:child[x]){
		ll nc, nw;
		tie(nc, nw) = dp(y);
		(way *= nw) %= mod;
		(way *= Comb(cnt+nc, cnt)) %= mod;
		cnt += nc;
	}
	cnt += 1;
	return {cnt, way};
}

void dfs_asgn(int x){
	int cnt=0, ys=0, is=0;
	for(auto tmp:edge[x]){
		int y, i; tie(y, i) = tmp;
		if(asgn[i]) continue;
		++cnt; ys+=y; is+=i;
	}
	if(cnt == 1){
		asgn[is] = 1 + (x>n);
		dfs_asgn(ys);
	}
}

int main()
{	
	read(n);
	for(int i=1; i<=2*n; ++i) fact[i]=fact[i-1]*i%mod;
	finv[2*n]=Pow(fact[2*n], -1);
	for(int i=2*n-1; 0<=i; --i) finv[i]=finv[i+1]*(i+1)%mod;
	
	for(int i=1, x, y; i<=2*n; ++i){
		read(x, y); d[i]={x, y};
		edge[x].eb(y+n, i);
		edge[y+n].eb(x, i);
		lx[x].eb(y, i);
		ly[y].eb(x, i);
	}
	
	for(auto& tmp:lx) sort(all(tmp.y));
	for(auto& tmp:ly) sort(all(tmp.y));
	
	ll ans = 1, ac = 0;
	
	for(int i=1; i<=2*n; ++i) if(!vis[i]){
		compn = ec = 0;
		dfs_compo(i);
		if(compn != ec/2){
			puts("0"); return 0;
		}
		cycn = 0;
		for(int j=0; j<compn; ++j) vis[comp[j]]=0;
		dfs_cyc(i, -1);
		
		for(int j=0; j<compn; ++j){
			dfs_asgn(comp[j]);
		}
		
		vector<int> ce(cycn), coe(compn);
		for(int i=0; i<cycn; ++i){
			for(auto tmp:edge[cyc[i]]){
				int y, e; tie(y, e) = tmp;
				if(y == cyc[(i+1)%cycn]){
					ce[i] = e;
					break;
				}
			}
		}
		for(int i=0, p=0; i<compn; ++i){
			int x = comp[i];
			for(auto tmp:edge[x]){
				if(!ins[tmp.y]) coe[p++]=tmp.y, ins[tmp.y]=1;
			}
		}
		
		ll cc = 0, cw = 0;
		
		for(int T=0; T<2; ++T){
			for(int i=0; i<cycn; ++i) asgn[ce[i]]=1+((T+i)&1);
			for(int i=0; i<compn; ++i){
				int x = coe[i];
				child[x].clear(); par[x] = -1;
			}
			for(int i=0; i<compn; ++i){
				int x = coe[i];
				vector<pp> *v;
				if(asgn[x] == 1){
					v = &lx[d[x].x];
				} else {
					v = &ly[d[x].y];
				}
				for(auto& tmp:*v){
					if(tmp.y == x) break;
					par[tmp.y] = x;
					child[x].pb(tmp.y);
				}
			}
			ll cnt = 0, way = 1;
			for(int i=0; i<compn; ++i){
				int x = coe[i];
				if(par[x] == -1){
					ll dc, dw; tie(dc, dw) = dp(x);
					(way *= dw * Comb(cnt + dc, dc) % mod) %= mod;
					cnt += dc;
				}
			}
			cc = cnt;
			cw += way;
		}
		
		(ans *= cw * Comb(ac + cc, cc) % mod) %= mod;
		ac += cc;
	}
	printf("%lld\n", ans);
	return 0;
}


Measured memory_bytes: 55296