#include<bits/stdc++.h>
#define lowbit(i) ((i)&(-(i)))
#define lson(i) ((i)<<1)
#define rson(i) ((i)<<1|1)
#define sqr(x) ((x)*(x))
#define fi first
#define se second
#define mp(x,y) make_pair((x),(y))
#define pb push_back
using namespace std;

typedef long long ll;
typedef unsigned long long ul;
typedef pair<int,int> pii;
typedef vector<int> vii;
typedef vector<pii> vpi;
typedef queue<int> qii;

const int inf=0x3f3f3f3f;
const int maxn=100007;
const int maxv=200007;
const int maxe=400007;
const int mod=1e9+7;

inline int read(){
	int re=0,flag=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-'){
			flag=-1;
		}
		ch=getchar();
	}
	while(isdigit(ch)){
		re=(re<<3)+(re<<1)+(ch-'0');
		ch=getchar();
	}
	return re*flag;
}

int n;
std::queue<int> q;
std::vector<int> cur;
int pre[maxe],now[maxe],son[maxe];
int tot;
int _pre[maxe],_now[maxe],_son[maxe];
int _tot;
int vis[maxv];
int ecnt;
int cir[maxv],deg[maxv],choose[maxv];
int fac[maxv],ifac[maxv];
int f[maxv],size[maxv];

int C(int a,int b){
	return 1ll*fac[a]*ifac[b]%mod*ifac[a-b]%mod;
}

int _ins(int a,int b){
	_pre[++_tot]=_now[a];
	_now[a]=_tot;
	_son[_tot]=b;
	return 0;
}

int calc(){
	for(auto i:cur){
		deg[i]=_now[i]=0;
	}
	for(auto i:cur){
		for(int j=now[i];j;j=pre[j]){
			int v=son[j];
			if(v<choose[i]){
				_ins(v,i);
				++deg[i];
			}
		}
	}
	for(auto i:cur){
		if(!deg[i]){
			q.push(i);
		}
		f[i]=1;
		size[i]=1;
	}
	int sz=0,ans=1;
	while(!q.empty()){
		int u=q.front();
		int flag=0;
		q.pop();
		for(int i=_now[u];i;i=_pre[i]){
			flag=1;
			int v=_son[i];
			--deg[v];
			size[v]+=size[u];
			f[v]=1ll*f[v]*f[u]%mod*C(size[v]-1,size[u])%mod;
			if(!deg[v]){
				q.push(v);
			}
		}
		if(!flag){
			sz+=size[u];
			ans=1ll*ans*f[u]%mod*C(sz,size[u])%mod;
		}
	}
	return ans;
}

int ins(int a,int b){
	pre[++tot]=now[a];
	now[a]=tot;
	son[tot]=b;
	return 0;
}

int dfs(int u){
	vis[u]=1;
	cur.push_back(u);
	for(int i=now[u];i;i=pre[i]){
		++ecnt;
		int v=son[i];
		if(!vis[v]){
			dfs(v);
		}
	}
	return 0;
}

int search(int u){
	cir[++cir[0]]=u;
	vis[u]=1;
	for(int i=now[u];i;i=pre[i]){
		int v=son[i];
		if(!vis[v]){
			search(v);
		}
	}
	return 0;
}

int solve(){
	if(cur.size()!=ecnt){
		return 0;
	}
	for(auto i:cur){
		if(deg[i]==1){
			q.push(i);
		}
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=now[u];i;i=pre[i]){
			int v=son[i];
			if(deg[v]!=1){
				--deg[v];
				choose[u]=v;
				if(deg[v]==1){
					q.push(v);
				}
			}
		}
	}
	int st=0;
	for(auto i:cur){
		if(deg[i]>1){
			st=i;
			vis[i]=0;
		}
	}
	cir[0]=0;
	search(st);
	cir[cir[0]+1]=cir[1];
	for(int i=1;i<=cir[0];++i){
		choose[cir[i]]=cir[i+1];
	}
	int res=calc();
	for(int i=2;i<=cir[0]+1;++i){
		choose[cir[i]]=cir[i-1];
	}
	res+=calc();
	if(res>=mod){
		res-=mod;
	}
	for(auto i:cur){
		vis[i]=1;
	}
	return res;
}

int main(){
	n=read();
	fac[0]=1;
	for(int i=1;i<=n<<1;++i){
		fac[i]=1ll*fac[i-1]*i%mod;
	}
	ifac[0]=ifac[1]=1;
	for(int i=2;i<=n<<1;++i){
		ifac[i]=1ll*(mod-mod/i)*ifac[mod%i]%mod;
	}
	for(int i=2; i<=n<<1; ++i){
		ifac[i]=1ll*ifac[i-1]*ifac[i]%mod;
	}
	for(int i=1; i<=n<<1; ++i){
		int x=read(),y=read();
		ins(x,y+n);
		ins(y+n,x);
		++deg[x];
		++deg[y+n];
	}
	int tsize=0,ans=1;
	for(int i=1;i<=n<<1;++i){
		if(!vis[i]){
			cur.clear();
			ecnt=0;
			dfs(i);
			ecnt/=2;
			int res=solve();
			tsize+=ecnt;
			ans=1ll*ans*res%mod*C(tsize,ecnt)%mod;
		}
	}
	printf("%d\n",ans);
	return 0;
}




Measured memory_bytes: 18804