#include <iostream>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<iomanip>
#include<ctime>
#include<set>
#include<map>
#include<queue>
#include<stack>
#define sqr(x) ((x)*(x))
#define fz1(i,n) for ((i)=1;(i)<=(n);(i)++)
#define fd1(i,n) for ((i)=(n);(i)>=1;(i)--)
#define fz0g(i,n) for ((i)=0;(i)<=(n);(i)++)
#define fd0g(i,n) for ((i)=(n);(i)>=0;(i)--)
#define fz0k(i,n) for ((i)=0;(i)<(n);(i)++)
#define fd0k(i,n) for ((i)=(long long)((n)-1);(i)>=0;(i)--)
#define fz(i,x,y) for ((i)=(x);(i)<=(y);(i)++)
#define fd(i,y,x) for ((i)=(y);(i)>=(x);(i)--)
#define fzin fz1(i,n)
#define fzim fz1(i,m)
#define fzjn fz1(j,n)
#define fzjm fz1(j,m)
#define ff(c,itr) for (__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define rdst(st,len){static char ss[len];scanf(" %s",ss);(st)=ss;}
//#define T_ int
using namespace std;
//struct bit{T_ arr[1000005];int lowbit(int x){return x&(-x);}void add(int x,T_ y){for (int i=x;i<=n;i+=lowbit(i)) arr[i]+=y;}T_ query(int x){T_ s=0;for (int i=x;i>0;i-=lowbit(i)) s+=arr[i];return s;}};
//struct seg{struct treedot{int l,r;T_ sum,add;void update(T_ x){sum+=(r-l+1)*x; add+=x;}}c[800005];void pushdown(int id){if (c[id].add){c[id*2].update(c[id].add);c[id*2+1].update(c[id].add);c[id].add=0;}}void pushup(int id){c[id].sum=c[id*2].sum+c[id*2+1].sum;}void build(int id,int l,int r){if (l>r) return;c[id].l=l;c[id].r=r;c[id].sum=0;c[id].add=0;if (l==r) c[id].sum=0;else{int mid=l+(r-l)/2;build(id*2,l,mid);build(id*2+1,mid+1,r);pushup(id);}}void update(int id,int le,int ri,T_ x){if (le>c[id].r||ri<c[id].l) return;if (le<=c[id].l&&c[id].r<=ri) c[id].update(x);else{pushdown(id);update(id*2,le,ri,x);update(id*2+1,le,ri,x);pushup(id);}}T_ query(int id,int le,int ri){if (ri<c[id].l||c[id].r<le) return 0;if (le<=c[id].l&&c[id].r<=ri) return c[id].sum;T_ ans=0;pushdown(id);ans+=query(id*2,le,ri);ans+=query(id*2+1,le,ri);pushup(id);return ans;}};
//struct bit_2d{T_ a[2005][2005];int lowbit(int x){return x&(-x);}void add(int x,int y,T_ z){int i,j;for (i=x;i<=2000;i+=lowbit(i)){for (j=y;j<=2000;j+=lowbit(j)){a[i][j]+=z;}}}T_ query(int x,int y){int i,j;T_ s=0;for (i=x;i;i-=lowbit(i)){for (j=y;j;j-=lowbit(j)){s+=a[i][j];}}return s;}T_ query(int x,int y,int xx,int yy){return query(xx,yy)-query(x-1,yy)-query(xx,y-1)+query(x-1,y-1);}};
int n,m,i,j,x,y,fac[200005],fi[200005],inv[200005],mod=1e9+7,vis[200005],ans=1,fa[200005],inc[200005],cnt,deg[200005],sz[200005];
vector<int> bi[200005],cir,all,bi2[200005];
void dfs1(int x,int p)
{
	fa[x]=p;vis[x]=1;cnt+=2;all.push_back(x);
	ff(bi[x],it){
		cnt--;if (*it==p) continue;
		if (!vis[*it]){
			dfs1(*it,x);
		}
		else if (cir.empty()){
			int t=x;
			cir.push_back(*it);inc[*it]=1;
			while (x!=*it){
				inc[x]=1;cir.push_back(x);x=fa[x];
			}x=t;
		}
	}
}
void dfs2(int x,int p)
{
	fa[x]=p;
	ff(bi[x],it){
		if (*it==p||inc[*it]) continue;
		dfs2(*it,x);
	}
}
void dfs3(int x,int p)
{
	ff(bi[x],it){
		if (*it==fa[x]) break;
//		cerr<<x<<' '<<*it<<endl;
		bi2[x].push_back(*it);
		deg[*it]++;
	}
	ff(bi[x],it){
		if (*it==p||inc[*it]) continue;
		dfs3(*it,x); 
	}
}
void init(){ff(all,it){bi2[*it].clear();deg[*it]=0;}}
int dfs4(int x,int p)
{
	deg[x]=-1;sz[x]=1;int ans=1;ff(bi2[x],it) if (*it!=p){
		deg[*it]=0;ans=1ll*ans*dfs4(*it,x)%mod;sz[x]+=sz[*it];
	}
	return 1ll*inv[sz[x]]*ans%mod;
}
int solve2()
{
	int i,s=1;
	ff(all,it) if (!deg[*it]) s=1ll*s*dfs4(*it,0)%mod;
	return s;
}
int solve(int x)
{
	int s=0;
	cnt=0;cir.clear();all.clear();dfs1(x,0);if (cnt) return 0;
	ff(cir,it) cerr<<*it<<' ';cerr<<endl;
	ff(cir,it) dfs2(*it,0);
	init();
	fz0k(i,cir.size()) fa[cir[i]]=cir[(i+1)%cir.size()];
	ff(cir,it) dfs3(*it,0);(s+=solve2())%=mod;//cerr<<"--------\n";
	init();
	fz0k(i,cir.size()) fa[cir[i]]=cir[(i+cir.size()-1)%cir.size()];
	ff(cir,it) dfs3(*it,0);(s+=solve2())%=mod;
	return s;
}
int main()
{
	scanf("%d",&n);
	fac[0]=fac[1]=inv[0]=inv[1]=fi[0]=fi[1]=1;
	fz(i,2,n+n){
		fac[i]=1ll*fac[i-1]*i%mod;
		inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
		fi[i]=1ll*fi[i-1]*inv[i]%mod;
	}
	fz1(i,n*2){
		scanf("%d%d",&x,&y);
		bi[x].push_back(y+n);
		bi[y+n].push_back(x);
	}
	fz1(i,n*2) if (!bi[i].empty()) sort(bi[i].begin(),bi[i].end());
	fz1(i,n*2) if (!vis[i]) ans=1ll*ans*solve(i)%mod;
	cout<<1ll*ans*fac[2*n]%mod<<endl;
	return 0;
}

Measured memory_bytes: 29304