#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<bitset>
#include<string>
#include<cstdio>
#include<cctype>
#include<cassert>
#include<cstdlib>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>

#define For(i,x,y) for (int i=x;i<y;i++)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define lf else if

#define dprintf(...) fprintf(stderr,__VA_ARGS__)
using namespace std;

typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef vector<int> Vi;

int IN(){
	int c,f,x;
	while (!isdigit(c=getchar())&&c!='-');c=='-'?(f=1,x=0):(f=0,x=c-'0');
	while (isdigit(c=getchar())) x=(x<<1)+(x<<3)+c-'0';return !f?x:-x;
}

const int N=200000+19;
const int p=1e9+7;

int Pow(int a,int b){
	int res=1;
	for (;b;b>>=1,a=1ll*a*a%p) if (b&1) res=1ll*res*a%p;
	return res;
}

struct Edge{
	int y,nxt;
} E[N*2];

Vi V[N],P;
int fac[N],inv[N],las[N],vis[N],chk[N],nxt[N],sz[N],deg[N];
int n,num,tmp,ans,cnt,v,e,a,b,v2,num2,tmp2,alb,x,y;

int C(int n,int m){
	return 1ll*fac[n]*inv[m]%p*inv[n-m]%p;
}
void Link(int x,int y){
	E[cnt]=(Edge){y,las[x]};las[x]=cnt++;
	E[cnt]=(Edge){x,las[y]};las[y]=cnt++;
}
void dfs(int x){
	vis[x]=1;
	v++;
	for (int i=las[x],y;~i;i=E[i].nxt){
		e++;
		if (!vis[y=E[i].y]) dfs(y);
	}
}
void dfs(int x,int fa){
	P.pb(x);
	chk[x]=1;
	for (int i=las[x],y;~i;i=E[i].nxt)
		if (i!=fa){
			if (!chk[y=E[i].y]){
				dfs(y,i^1);
			} else{
				a=x,b=y;
			}
		}
}
void gao(int x,int fa){
	for (int i=las[x],y;~i;i=E[i].nxt)
		if ((y=E[i].y)!=fa){
			if (x==a&&y==b) continue;
			if (x==b&&y==a) continue;
			nxt[y]=x;
			gao(y,x);
		}
}
int bao(int x){
	chk[x]=2;
	int ans=1;
	sz[x]=0;
	for (int y:V[x]){
		ans=1ll*ans*bao(y)%p*C(sz[x]+sz[y],sz[y])%p;
		sz[x]+=sz[y];
	}
	sz[x]++;
	return ans;
}
void Work(int x){
	P.clear();
	tmp=0;
	dfs(x,-1);
	
	alb=1;
	gao(a,-1);
	nxt[a]=b;
	for (int i:P) if (i<nxt[nxt[i]]){
		V[nxt[i]].pb(i);
		deg[i]++;
	}
	num2=0;
	for (int i:P) if (deg[i]==0&&chk[i]!=2){
		alb=1ll*alb*bao(i)%p*C(num2+sz[i],sz[i])%p;
		num2+=sz[i];
	}
	for (int i:P){
		V[i].clear();
		deg[i]=0;
		chk[i]=0;
	}
	//printf("%d\n",alb);
	tmp=(tmp+alb)%p;
	
	alb=1;
	gao(b,-1);
	nxt[b]=a;
	for (int i:P) if (i<nxt[nxt[i]]){
		V[nxt[i]].pb(i);
		deg[i]++;
	}
	num2=0;
	for (int i:P) if (deg[i]==0&&chk[i]!=2){
		alb=1ll*alb*bao(i)%p*C(num2+sz[i],sz[i])%p;
		num2+=sz[i];
	}
	//printf("%d\n",alb);
	tmp=(tmp+alb)%p;
}

int main(){
	memset(las,-1,sizeof(las));
	fac[0]=1;
	For(i,1,N) fac[i]=1ll*fac[i-1]*i%p;
	inv[N-1]=Pow(fac[N-1],p-2);
	for (int i=N-1;i;i--) inv[i-1]=1ll*inv[i]*i%p;
	n=IN()*2;
	For(i,1,n+1){
		x=IN(),y=IN();
		Link(x,y+n/2);
	}
	ans=1;
	For(i,1,n+1) if (!vis[i]){
		v=0,e=0;
		dfs(i);
		if (v!=e/2){
			puts("0");
			return 0;
		}
		Work(i);
		ans=1ll*ans*tmp%p*C(num+v,v)%p;
		num+=v;
	}
	printf("%d\n",ans);
}