#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define int long long
const int N=2e5+10,p=1e9+7;
int n,m,mp[N],fa[N],ln[N],dn[N];
struct P{int x,y,id;}o[N];
inline bool cmpx(P u,P v){return u.x<v.x;}
inline bool cmpy(P u,P v){return u.y<v.y;}
inline bool cmpid(P u,P v){return u.id<v.id;}
vector<int> g[N];
int no,nosi,fac[N],inv[N];
inline int ask(int x){
	return fa[x]==x?x:fa[x]=ask(fa[x]);
}
inline int C(int x,int y){
	return fac[x]*inv[x-y]%p*inv[y]%p;
}
set<int> se;
queue<int> q;
inline void merge(int &x,int &six,int y,int siy){
	six+=siy;
	x=x*y%p*C(six,siy)%p;
}
int rd[N],fx[N];
//fx:0:×ó 1:ÏÂ 
vector<pair<int,int> > cb[N];
vector<int> ip;

int tot,fi[N],a[N<<2],ne[N<<2],si[N];
inline void add(int x,int y){
	a[++tot]=y;ne[tot]=fi[x];fi[x]=tot;
}
inline int dfs(int x){
	si[x]=0;int ans=1,t;
	for (int i=fi[x];i;i=ne[i]) t=dfs(a[i]),merge(ans,si[x],t,si[a[i]]);
	++si[x];
	return ans;
}
bool flag[N];
inline int build(const vector<int> &g){
	int gs=g.size();
	tot=0;for (int i=0;i<gs;++i) flag[g[i]]=1,fi[g[i]]=si[g[i]]=0;
	for (int i=0;i<gs;++i) 
		if (fx[g[i]]==0){
			int t=ln[g[i]];
			while (t){
				add(g[i],t);flag[t]=0;
				if (fx[t]==0) break;
				t=ln[t];
			}
		}else{
			int t=dn[g[i]];
			while (t){
				add(g[i],t);flag[t]=0;
				if (fx[t]==1) break;
				t=dn[t];
			}
			
		}
	int ans=1,anssi=0,t;
	for (int i=0;i<gs;++i) if (flag[g[i]]) t=dfs(g[i]),merge(ans,anssi,t,si[g[i]]);
	return ans;
}
inline int solve(const vector<int> &g){
	int gs=g.size();
	while (!q.empty()) q.pop();se.clear();
	for (int i=0;i<gs;++i) se.insert(o[g[i]].x),se.insert(o[g[i]].y+n);
	for (set<int>::iterator it=se.begin();it!=se.end();++it) if (rd[*it]==1) q.push(*it);
	while (!q.empty()){
		int u=q.front();q.pop();
		for (vector<pair<int,int> >::iterator it=cb[u].begin();it!=cb[u].end();++it)
		if (rd[it->first]>1){
			fx[it->second]=u<=n;
			if (--rd[it->first]==1) q.push(it->first);
		}
	}
	for (set<int>::iterator it=se.begin();it!=se.end();++it) if (rd[*it]!=1&&rd[*it]!=2) return 0;
	int nt=-1;
	for (set<int>::iterator it=se.begin();it!=se.end();++it) if (rd[*it]==2) {nt=*it;break;}
	if (nt==-1) return build(g);
	ip.clear();
	int ntt=nt;
	ok:;
	for (vector<pair<int,int> >::iterator it=cb[nt].begin();it!=cb[nt].end();++it)
		if (rd[it->first]>1&&it->first!=ntt){
			--rd[it->first];
			ip.push_back(it->second);
			fx[it->second]=nt<=n;
			nt=it->first;
			goto ok;
		}
	for (vector<pair<int,int> >::iterator it=cb[nt].begin();it!=cb[nt].end();++it)
		if (rd[it->first]>1){
			--rd[it->first];
			ip.push_back(it->second);
			fx[it->second]=nt<=n;
		}
	
	int ans=build(g);
	for (int i=0;i<ip.size();++i) fx[ip[i]]^=1;
	return ans+build(g);
}
main(){
	scanf("%lld",&n);m=n<<1;
	for (int i=1;i<=m;++i) 
		scanf("%lld%lld",&o[i].x,&o[i].y),o[i].id=i,
		cb[o[i].x].push_back(make_pair(o[i].y+n,i)),
		cb[o[i].y+n].push_back(make_pair(o[i].x,i)),
		++rd[o[i].x],++rd[o[i].y+n];
	sort(o+1,o+m+1,cmpx);
	for (int i=1;i<=n;++i) mp[i]=0;
	for (int i=1;i<=m;++i) ln[o[i].id]=mp[o[i].y],mp[o[i].y]=o[i].id;
	sort(o+1,o+m+1,cmpy);
	for (int i=1;i<=n;++i) mp[i]=0;
	for (int i=1;i<=m;++i) dn[o[i].id]=mp[o[i].x],mp[o[i].x]=o[i].id;
	sort(o+1,o+m+1,cmpid);
	
	fac[0]=1;for (int i=1;i<=m;++i) fac[i]=fac[i-1]*i%p;
	inv[0]=inv[1]=1;for (int i=2;i<=m;++i) inv[i]=inv[p%i]*(p-p/i)%p;
	for (int i=2;i<=m;++i) inv[i]=inv[i]*inv[i-1]%p;
	
	for (int i=1;i<=m;++i) fa[i]=i;
	for (int i=1;i<=m;++i){
		if (dn[i]) fa[ask(i)]=ask(dn[i]);
		if (ln[i]) fa[ask(i)]=ask(ln[i]);
	}
	for (int i=1;i<=m;++i) g[ask(i)].push_back(i);
	int ans=1,anssi=0;
	for (int i=1;i<=m;++i) if (fa[i]==i) merge(ans,anssi,solve(g[i]),g[i].size()); 
	printf("%lld",ans);
	return 0;
}

Measured memory_bytes: 60148