#include<bits/stdc++.h>
#define pb push_back

using namespace std;
typedef long long ll;

const int N=2e5+5,P=1e9+7;
inline int fpow(int a,int t){static int r;for(r=1;t;t>>=1,a=(ll)a*a%P)if(t&1)r=(ll)r*a%P;return r;}
int n,fac[N],ifac[N],ans=1,m,now;
inline int C(int n,int m){return (ll)fac[n]*ifac[m]%P*ifac[n-m]%P;}

bool vi[N];
vector<int>e[N];
int id[N],idc,s1,s2,fa[N],pa[N];

void dfs(int x){
	vi[x]=true;id[++idc]=x;
	if(x<=n)s1++;else s2++;
	sort(e[x].begin(),e[x].end());
	for(int v:e[x])if(fa[x]!=v){
		fa[v]=x;if(!vi[v])dfs(v);
	}
}
int find(int x){
	if(vi[x])return x; 
	vi[x]=true;
	int t=0;
	for(int v:e[x])if(pa[x]!=v){pa[v]=x,t=find(v);if(t)break;}
	vi[x]=false;
	return t;
}

int sz[N],in[N];
vector<int>E[N];

int solve(int x){
	int r=1;
	for(int v:E[x]){
		r=(ll)r*solve(v)%P;
		r=(ll)r*C(sz[x]+sz[v],sz[v])%P;
		sz[x]+=sz[v];
	}
	sz[x]++;
	return r;
}

int calc(){
	for(int i=1,u;i<=idc;i++)
		for(int x:e[u=id[i]]){
			if(x==fa[u])break;
			E[u].pb(x),in[x]++;
		}
	for(int i=1,u;i<=idc;i++)if(!in[u=id[i]])E[0].pb(u),in[u]++;
	int ans=solve(0);
	for(int i=0,u;i<=idc;i++)E[u=id[i]].clear(),in[u]=sz[u]=0;
	return ans;
}

int main(){
	scanf("%d",&n);
	fac[0]=1;
	for(int i=1;i<=2*n;i++)fac[i]=(ll)fac[i-1]*i%P;
	ifac[2*n]=fpow(fac[2*n],P-2);
	for(int i=2*n;i>=1;i--)ifac[i-1]=(ll)ifac[i]*i%P;
	for(int i=1,x,y;i<=2*n;i++)scanf("%d%d",&x,&y),e[x].pb(y+n),e[y+n].pb(x);
	for(int i=1;i<=2*n;i++)if(!vi[i]){
		int R=find(i);
		if(!R){ans=0;break;}
		dfs(R);
		int se=0;
		for(int k=1;k<=idc;k++)se+=e[id[k]].size();se>>=1;
		if(se!=s1+s2){ans=0;break;}
		now=calc();
		for(int x=pa[R]=fa[R];x!=R;x=pa[x]=fa[x]);
		fa[pa[R]]=R;
		for(int x=pa[R];x!=R;x=pa[x])fa[pa[x]]=x;
		now=(now+calc())%P;
		ans=(ll)ans*now%P*C(m+idc,m)%P;
		m+=idc;
		while(idc)id[idc--]=0;s1=s2=0;
	}
	printf("%d\n",ans);
	return 0;
}