#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define pb push_back
#define ref(i,x,y)for(int i=x;i<=y;++i)
#define def(i,x,y)for(int i=x;i>=y;--i)
typedef long long LL;
int read(){
	char c=getchar();int d=0,f=1;
	for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
	for(;c>='0'&&c<='9';d=d*10+c-48,c=getchar());
	return d*f;
}
const int N=200100,mod=1e9+7;
bool instk[N];
int n,tp,top,tmpr,ans,w[N],res,f[N],mkx[N],mky[N],F[N],vis[N],stk[N],h[N],t[N];
struct xint{int x,y;}p[N];
vector<int> vx[N],vy[N];

int cnt,head[N];
struct Xint{int to,next;}V[N*8];
void add(int x,int y){
	V[++cnt]=(Xint){y,head[x]};head[x]=cnt;
	V[++cnt]=(Xint){x,head[y]};head[y]=cnt;
}

bool cmpx(int a,int b){return p[a].x<p[b].x;}
bool cmpy(int a,int b){return p[a].y<p[b].y;}
void nosolution(){
	printf("0\n");exit(0);
}
void dfs(int f,int x){
	if(instk[x]){
		for(int i=top;i>0;i--){
			h[++h[0]]=stk[i];
			if(stk[i]==x)break;
		}return;
	}
	if(vis[x])return;
	if(!mkx[p[x].x])tmpr++;mkx[p[x].x]=1;
	if(!mky[p[x].y])tmpr++;mky[p[x].y]=1;
	tmpr--;
	vis[x]=1;
	stk[++top]=x;instk[x]=1;
	for(int i=head[x];i;i=V[i].next){
		int y=V[i].to;if(y!=f)dfs(x,y);
	}
	stk[top--]=0;instk[x]=0;
}
int dfs(int x){
	vis[x]=tp;
	t[x]=0;
	int X=p[x].x,Y=p[x].y,sum=1;
	if(w[x]==1){
		int sz=vx[X].size();
		ref(i,0,sz-1)if(vx[X][i]!=x&&vis[vx[X][i]]!=tp){
			int y=vx[X][i];w[y]=2;
			int s=dfs(y);
			if(p[y].y<Y){
				t[x]+=t[y];
				sum=(LL)sum*F[t[y]]%mod*s%mod;
			}else res=(LL)res*F[t[y]]%mod*s%mod;
		}
	}
	if(w[x]==2){
		int sz=vy[Y].size();
		ref(i,0,sz-1)if(vy[Y][i]!=x&&vis[vy[Y][i]]!=tp){
			int y=vy[Y][i];w[y]=1;
			int s=dfs(y);
			if(p[y].x<X){
				t[x]+=t[y];
				sum=(LL)sum*F[t[y]]%mod*s%mod;
			}else res=(LL)res*F[t[y]]%mod*s%mod;
		}
	}
	sum=(LL)sum*f[t[x]]%mod;
	t[x]++;
	return sum;
}
void work(int x){
	tmpr=0;h[0]=0;dfs(0,x);
	if(tmpr!=0)nosolution();
	int o=0,xx,yy,s=0,Res=0;res=1;
	ref(i,1,h[0])if(!o||xx<p[h[i]].x||xx==p[h[i]].x&&yy<p[h[i]].y)
		o=h[i],xx=p[h[i]].x,yy=p[h[i]].y;
	tp=2;w[o]=1;s=dfs(o);Res=(Res+(LL)res*F[t[o]]%mod*s%mod)%mod;res=1;
	tp=3;w[o]=2;s=dfs(o);Res=(Res+(LL)res*F[t[o]]%mod*s%mod)%mod;
	ans=(LL)ans*Res%mod;
}
int mi(int a,int b){
	int s=1;
	for(;b;b>>=1,a=(LL)a*a%mod)
		if(b&1)s=(LL)s*a%mod;
	return s;
}
void init(){
	f[0]=F[0]=1;
	ref(i,1,n)f[i]=(LL)f[i-1]*i%mod;
	F[n]=mi(f[n],mod-2);
	def(i,n-1,1)F[i]=(LL)F[i+1]*(i+1)%mod;
}
int main(){
	n=read();n=n*2;
	ref(i,1,n)p[i].x=read(),p[i].y=read();
	ref(i,1,n)vx[p[i].x].pb(i),vy[p[i].y].pb(i);
	ref(i,1,n/2)if(!vx[i].empty()){
		sort(vx[i].begin(),vx[i].end(),cmpy);
		int s=vx[i].size();
		ref(j,0,s-2)add(vx[i][j],vx[i][j+1]);
	}
	ref(i,1,n/2)if(!vy[i].empty()){
		sort(vy[i].begin(),vy[i].end(),cmpx);
		int s=vy[i].size();
		ref(j,0,s-2)add(vy[i][j],vy[i][j+1]);
	}
	init();ans=f[n];
	ref(i,1,n)if(!vis[i])work(i);
	printf("%d\n",ans);
}