//by yjz
#include<bits/stdc++.h>
using namespace std;
#define FF first
#define SS second
#define PB push_back
#define MP make_pair
#define bged(v) (v).begin(),(v).end()
#define foreach(it,s) for(__typeof((s).begin()) it=(s).begin();it!=(s).end();it++)
typedef long long ll;
const int Imx=2147483647;
const ll Lbig=2e18;
const int mod=1e9+7;
//My i/o stream
struct fastio
{
	char s[100000];
	int it,len;
	fastio(){it=len=0;}
	inline char get()
	{
		if(it<len)return s[it++];it=0;
		len=fread(s,1,100000,stdin);
		if(len==0)return EOF;else return s[it++];
	}
	bool notend()
	{
		char c=get();
		while(c==' '||c=='\n')c=get();
		if(it>0)it--;
		return c!=EOF;
	}
}_buff;
#define geti(x) x=getnum()
#define getii(x,y) geti(x),geti(y)
#define getiii(x,y,z) getii(x,y),geti(z)
#define puti(x) putnum(x),putchar(' ')
#define putii(x,y) puti(x),puti(y)
#define putiii(x,y,z) putii(x,y),puti(z)
#define putsi(x) putnum(x),putchar('\n')
#define putsii(x,y) puti(x),putsi(y)
#define putsiii(x,y,z) putii(x,y),putsi(z)
inline ll getnum()
{
	ll r=0;bool ng=0;char c;c=_buff.get();
	while(c!='-'&&(c<'0'||c>'9'))c=_buff.get();
	if(c=='-')ng=1,c=_buff.get();
	while(c>='0'&&c<='9')r=r*10+c-'0',c=_buff.get();
	return ng?-r:r;
}
template<class T> inline void putnum(T x)
{
	if(x<0)putchar('-'),x=-x;
	register short a[20]={},sz=0;
	while(x)a[sz++]=x%10,x/=10;
	if(sz==0)putchar('0');
	for(int i=sz-1;i>=0;i--)putchar('0'+a[i]);
}
inline char getreal(){char c=_buff.get();while(c<=32)c=_buff.get();return c;}
ll qpow(ll x,ll k){return k==0?1:1ll*qpow(1ll*x*x%mod,k>>1)*(k&1?x:1)%mod;}
ll fac[200111],ifac[200111];
int n;
int head[200111],nxt[400111],to[400111],tot=1;
int f[200111];
int gf(int x){return f[x]==x?x:f[x]=gf(f[x]);}
int tcnt[200111];
vector<int> g[200111];
bool vis[200111];
int pe[200111];
vector<int> cyc,cyce;
int st[200111],stn;
bool onc[200111],inst[200111];
void dfs(int x,int pre=-1)
{
//	cerr<<"dfs:"<<x<<","<<pre<<endl;
	st[stn++]=x;vis[x]=inst[x]=1;
	for(int i=head[x];i;i=nxt[i])
	{
		int u=to[i];
		if(u==pre)continue;
		if(!vis[u])pe[u]=i,dfs(u,x);
		else if(inst[u])
		{
			int it=stn-1;
			while(true)
			{
				cyc.PB(st[it]);
				onc[st[it]]=1;
				if(st[it]==u)
				{
					cyce.PB(i);
					break;
				}
				else cyce.PB(pe[st[it]]);
				it--;
			}
		}
	}
	stn--;inst[x]=0;
}
int mt[200111],sz[200111];
vector<int> con[200111];
void calcsz(int x)
{
	sz[x]=1;
	for(int i=0;i<con[x].size();i++)
	{
		int u=con[x][i];
		if(!sz[u])calcsz(u);
		sz[x]+=sz[u];
	}
}
ll calc(vector<int> v)
{
//	for(int i=1;i<=n;i++)cerr<<mt[i]<<":"<<to[mt[i]^1]<<","<<to[mt[i]]<<" ";cerr<<endl;
	for(int i=0;i<v.size();i++)
	{
		int x=v[i];
		for(int j=head[x];j;j=nxt[j])con[j>>1].clear(),sz[j>>1]=0;
	}
	for(int i=0;i<v.size();i++)
	{
		int x=v[i];
		for(int j=head[x];j;j=nxt[j])
		{
			if(to[j]<to[mt[x]])
			{
				con[mt[x]>>1].PB(j>>1);
			}
		}
	}
	ll ret=1;
	for(int i=0;i<v.size();i++)
	{
		int x=v[i];
		for(int j=head[x];j;j=nxt[j])
		{
			if(!sz[j>>1])
			{
				calcsz(j>>1);
			}
		}
	}
	for(int i=0;i<v.size();i++)ret=ret*sz[mt[v[i]]>>1]%mod;
	return ret;
}
void dfs2(int x,int pre=-1)
{
	for(int i=head[x];i;i=nxt[i])
	{
		int u=to[i];
		if(onc[u]||u==pre)continue;
		mt[u]=i^1;
		dfs2(u,x);
	}
}
ll solve(vector<int> v)
{
//	cerr<<"solve:"<<endl;
//	for(int i=0;i<v.size();i++)cerr<<v[i]<<" ";cerr<<endl;
	cyc.clear();
	cyce.clear();
	dfs(v[0]);
//	for(int i=0;i<cyc.size();i++)cerr<<cyc[i]<<" ";cerr<<endl;
//	for(int i=0;i<cyce.size();i++)cerr<<to[cyce[i]^1]<<","<<to[cyce[i]]<<" ";cerr<<endl;
	
	for(int i=0;i<cyc.size();i++)
	{
		dfs2(cyc[i]);
	}
	ll ans=0;
	for(int i=0;i<cyce.size();i++)
	{
		int e=cyce[i];
		mt[to[e^1]]=e;
	}
	ans+=fac[v.size()]*qpow(calc(v),mod-2)%mod;
	for(int i=0;i<cyce.size();i++)
	{
		int e=cyce[i];
		mt[to[e]]=e^1;
	}
	ans+=fac[v.size()]*qpow(calc(v),mod-2)%mod;
	return ans;
}
int main()
{
	fac[0]=1;
	for(int i=1;i<=200005;i++)fac[i]=fac[i-1]*i%mod;
	ifac[200005]=qpow(fac[200005],mod-2);
	for(int i=200004;i>=0;i--)ifac[i]=ifac[i+1]*(i+1)%mod;
	geti(n);
	for(int i=1;i<=2*n;i++)f[i]=i;
	for(int i=1;i<=2*n;i++)
	{
		int x,y;
		getii(x,y);
		y+=n;
//		cerr<<x<<","<<y<<endl;
		nxt[++tot]=head[x];
		head[x]=tot;
		to[tot]=y;
		nxt[++tot]=head[y];
		head[y]=tot;
		to[tot]=x;
		f[gf(x)]=gf(y);
	}
	n*=2;
	for(int i=1;i<=n;i++)tcnt[gf(to[i<<1])]++,tcnt[gf(i)]--,g[gf(i)].PB(i);
	for(int i=1;i<=n;i++)
	{
		if(tcnt[i]!=0)
		{
			puts("0");
			return 0;
		}
	}
	ll ans=fac[n];
	for(int i=1;i<=n;i++)
	{
		if(g[i].size()>0)
		{
			ll cur=solve(g[i]);
			ans=ans*cur%mod*ifac[g[i].size()]%mod;
		}
	}
	cout<<ans<<endl;
	return 0;
}


Measured memory_bytes: 32484