#include"bits/stdc++.h"


#define PB push_back
#define PF push_front
#define LB lower_bound
#define UB upper_bound
#define fr(x) freopen(x,"r",stdin)
#define fw(x) freopen(x,"w",stdout)
#define iout(x) printf("%d\n",x)
#define lout(x) printf("%lld\n",x)
#define REP(x,l,u) for(int x = (l);x<=(u);x++)
#define RREP(x,l,u) for(int x = (l);x>=(u);x--)
#define mst(x,a) memset(x,a,sizeof(x))
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define MP make_pair
#define se second
#define fi first
#define dbg(x) cout<<#x<<" = "<<(x)<<endl;
#define sz(x) ((int)x.size())
#define cl(x) x.clear()

typedef  long long ll;
typedef unsigned long long ull;
typedef double db;
typedef long double ld;
using namespace std;

const int maxn = 200010;
const int mod = 1e9+7;
const int MAX = 1000000010;
const double eps = 1e-6;
const double PI = acos(-1);

template<typename T> inline void read(T &x){
x=0;T f=1;char ch;do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');do x=x*10+ch-'0',ch=getchar();while(ch<='9'&&ch>='0');x*=f;
}

template<typename A,typename B> inline void read(A&x,B&y){read(x);read(y);}
template<typename A,typename B,typename C> inline void read(A&x,B&y,C&z){read(x);read(y);read(z);}
template<typename A,typename B,typename C,typename D> inline void read(A&x,B&y,C&z,D&w){read(x);read(y);read(z);read(w);}
template<typename A,typename B> inline A fexp(A x,B p){A ans=1;for(;p;p>>=1,x=1LL*x*x%mod)if(p&1)ans=1LL*ans*x%mod;return ans;}
template<typename A,typename B> inline A fexp(A x,B p,A mo){A ans=1;for(;p;p>>=1,x=1LL*x*x%mo)if(p&1)ans=1LL*ans*x%mo;return ans;}

int n,ans=1;

vector<PII> G[maxn];
vector<int> G2[maxn];
vector<int> Ver;

int fac[maxn],inv[maxn];

int Cir[maxn],E[maxn],tot;

int fa[maxn],vi[maxn],Len[maxn],Iscir[maxn];

int dp[maxn],size[maxn],Val[maxn],hasfa[maxn];

void dfs(int u,int f){
	fa[u]=f;vi[u]=1;Ver.PB(u);
	for(auto v:G[u])if(v.se!=f){
		if(!vi[v.se])Len[v.se]=v.fi,dfs(v.se,u);
		else{
			if(Iscir[v.se])continue;
			int x=u;
			for(;;){
				Cir[++tot]=x;E[tot]=Len[x];
				Iscir[x]=1;
				if(x==v.se)break;
				x=fa[x];
			}
			E[tot]=v.fi;
		}
	}
}

void dfs2(int u,int f){
	for(auto v:G[u])if(v.se!=f&&!Iscir[v.se]){
		Val[v.se]=v.fi;
		dfs2(v.se,u);
	}
}

void dfs3(int u){
	size[u]=1;
	for(auto v:G2[u]){
		dfs3(v);
		size[u]+=size[v];
	}
	dp[u]=fac[size[u]-1];
	for(auto v:G2[u])dp[u]=1ll*dp[u]*dp[v]%mod*inv[size[v]]%mod;
}

void addedge(int u,int v){
	hasfa[v]=1;
	G2[u].PB(v);
//	cout<<u<<' '<<v<<endl;
}

int solve(int x){
	Ver.clear();
	int ans=0,res,N;
	tot=0;
	dfs(x,0);
	N=Ver.size();
	for(auto x:Ver)if(Iscir[x])dfs2(x,0);
	REP(i,1,tot)Val[Cir[i]]=E[i];
	for(auto x:Ver)hasfa[x]=0,G2[x].clear();
	for(auto x:Ver){
		for(auto v:G[x])if(Val[x]!=v.fi)if(Val[x]>Val[v.se])addedge(x,v.se);
	}
	res=fac[N];
	for(auto x:Ver)if(!hasfa[x]){
		dfs3(x);
//		REP(i,1,n)cout<<size[i]<<' ';cout<<endl;
		res=1ll*dp[x]*res%mod*inv[size[x]]%mod;
	}
	ans=(ans+res)%mod;
//	cout<<ans<<endl;
//	cout<<"!\n";
	REP(i,1,tot)Val[Cir[i]]=(i==1?E[tot]:E[i-1]);
//	REP(i,1,tot)cout<<E[i]<<' ';cout<<endl;
//	REP(i,1,tot)cout<<Val[i]<<' ';cout<<endl;
	for(auto x:Ver)hasfa[x]=0,G2[x].clear();
	for(auto x:Ver){
		for(auto v:G[x])if(Val[x]!=v.fi)if(Val[x]>Val[v.se])addedge(x,v.se);
	}
	res=fac[N];
	for(auto x:Ver)if(!hasfa[x]){
		dfs3(x);
//		REP(i,1,n)cout<<size[i]<<' ';cout<<endl;
		res=1ll*res*dp[x]%mod*inv[size[x]]%mod;
//		cout<<dp[x]<<endl;
//		cout<<ans<<endl;
//		cout<<"!\n";
//		cout<<size[x]<<endl;
	}
	ans=(ans+res)%mod;
//	cout<<ans<<endl;
	ans=1ll*ans*inv[N]%mod;
	return ans;
}

void Work(){
	REP(i,1,n)if(!vi[i])ans=1ll*ans*solve(i)%mod;
	REP(i,1,n)ans=1ll*ans*i%mod;
	iout(ans);
}

int dsu[maxn],has_circle[maxn];

int find(int i){
	return dsu[i]==i?i:dsu[i]=find(dsu[i]);
}

void Init(){
	read(n);
	REP(i,1,n*2)dsu[i]=i;
	REP(i,1,n*2){
		int x,y;
		read(x,y);
		G[x].PB(MP(x+y,y+n));G[y+n].PB(MP(x+y,x));
		y+=n;
		x=find(x);y=find(y);
		if(x==y){
			if(has_circle[x]){
				puts("0");
				exit(0);
			}
			has_circle[x]=1;
		}
		else{
			if(has_circle[x]&&has_circle[y]){
				puts("0");
				exit(0);
			}
			else{
				dsu[x]=y;
				has_circle[y]|=has_circle[x];
			}
		}
	}
	n<<=1;
	fac[0]=1;
	REP(i,1,n)fac[i]=1ll*fac[i-1]*i%mod;
	REP(i,0,n)inv[i]=fexp(fac[i],mod-2);
}

int main(){
	Init();
	Work();
	return 0;
}


Measured memory_bytes: 33400