#include<bits/stdc++.h>
#define LL long long
#define int LL
#define P pair<int,int>
#define fi first
#define se second
const LL N=2e5+10;
const LL mod=1e9+7;
const LL inf=0x3f3f3f;
const double eps=1e-9;
using namespace std;
template<typename tp> inline void read(tp &x)
{
    x=0;char c=getchar();
    bool f=0; for(; c<'0'||c>'9'; f|=(c=='-'),c = getchar());
    for(; c>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0',c = getchar());
    if(f) x=-x;
}
P wei[N<<1];
map<P,int> Map;
vector<P> idd;
vector<int> line[N],row[N],vec,node;
  
int n,found;
int head[N<<1],cnt;
int fa[N<<1],side[N<<1],vis[N<<1];
int tou[N<<1],num;
LL siz[N<<1];
  
struct Node { int next,to,id;} edge[N<<3];
struct E {int next,to;} e[N<<3];
  
void add(int from,int to,int id) { edge[++cnt]= {head[from],to,id}; head[from]=cnt;}
void insert(int from,int to,int id) { add(from,to,id); add(to,from,id);}
void jia(int from,int to) {e[++num]= {tou[from],to}; tou[from]=num;}
P calc(int x,int y) { if(x>y) swap(x,y); y-=n; return P(x,y);}
LL KSM(LL a,LL b,LL ret=1) { while(b) { if(b&1) ret=ret*a%mod; a=a*a%mod; b>>=1; } return ret;}
int ask(P x) { return lower_bound(idd.begin(),idd.end(),x)-idd.begin()+1;}
 
void dfs(int now,int fath)
{
    vis[now]=1;
    for(int i=head[now]; i; i=edge[i].next)
    {
        if(found==1) return ;
        int to=edge[i].to;
        if(to==fath) continue;
        if(vis[to])
        {
            int flag=now;
            while(flag!=to)
            {
                vec.push_back(flag);
                flag=fa[flag];
            }
            vec.push_back(to);
            found = 1;
            return ;
        }
        fa[to]=now;
        dfs(to,now);
    }
}
void dfs_side_other(int now,int fa)
{
    for(int i=head[now]; i; i=edge[i].next)
    {
        int to=edge[i].to;
        if(vis[to]==2||to==fa)
            continue;
        vis[to]=1;
        if(to>n) side[edge[i].id]=2;
        else side[edge[i].id]=1;
        node.push_back(edge[i].id);
        dfs_side_other(to,now);
    }
}
LL dfs_size(int now)
{
    if(siz[now]) return siz[now];
    siz[now]=1;
    for(int i=tou[now]; i; i=e[i].next)
    {
        int to=e[i].to;
        siz[now]+=dfs_size(to);
    }
    return siz[now];
}
void built()
{
    for(int i=0; i<node.size(); i++)
    {
        int x=wei[node[i]].fi,y=wei[node[i]].se;
        if(side[node[i]]==1)
        {
            int pos=lower_bound(line[x].begin(),line[x].end(),y)-line[x].begin() - 1;
            for(int j=0;j<=pos;j++)
                jia(node[i],ask(P(x,line[x][j])));
        }
        else
        {
            int pos=lower_bound(row[y].begin(),row[y].end(),x)-row[y].begin() - 1;
            for(int j=0;j<=pos;j++)
                jia(node[i],ask(P(row[y][j],y)));
        }
    }
}
LL solve(int now)
{
    found = 0;
    LL ret1=1,ret2=1;
    vec.clear(), node.clear();
    dfs(now,now);
    for(int i=0; i<vec.size(); i++) vis[vec[i]]=2;
    for(int i=0; i<vec.size(); i++) dfs_side_other(vec[i],vec[i]);
    for(int i=0; i<vec.size()-1; i++)
    {
        side[ask(calc(vec[i],vec[i+1]))]=(vec[i+1]>n?1:2);
        node.push_back(ask(calc(vec[i],vec[i+1])));
    }
    side[ask(calc(vec[vec.size()-1],vec[0]))]=(vec[0]>n?1:2);
    node.push_back(ask(calc(vec[vec.size()-1],vec[0])));
    for(int i=0; i<node.size(); i++) siz[node[i]]=0;
    built();
    for(int i=0; i<node.size(); i++)
        ret1=ret1*KSM(dfs_size(node[i]),mod-2)%mod;
    num=0;
    for(int i=0; i<node.size(); i++) tou[node[i]]=0;
    for(int i=vec.size()-1; i>0; i--)
        side[ask(calc(vec[i],vec[i-1]))]=(vec[i-1]>n?1:2);
    side[ask(calc(vec[0],vec[vec.size()-1]))]=(vec[vec.size()-1]>n?1:2);
    for(int i=0; i<node.size(); i++) siz[node[i]]=0;
    built();
    for(int i=0; i<node.size(); i++)
        ret2=ret2*KSM(dfs_size(node[i]),mod-2)%mod;
    return ret1+ret2;
}
signed main()
{
    read(n);
    for(int i=1,x,y; i<=n*2; i++)
    {
        read(x),read(y);
        idd.push_back(P(x,y));
        line[x].push_back(y);
        row[y].push_back(x);
    }
    sort(idd.begin(),idd.end());
    for(int i=0;i<n*2;i++)
    {
        wei[i+1]=idd[i];
        insert(idd[i].fi,idd[i].se+n,i+1);
    }
    for(int i=1; i<=n; i++)
    {
        sort(line[i].begin(),line[i].end()),
        sort(row[i].begin(),row[i].end());
        if(!line[i].size()||!row[i].size())
            return 0*puts("0");
    }
    LL ans=1;
    for(int i=1; i<=n*2; i++)
        if(!vis[i])
            ans=ans*solve(i)%mod;
    for(int i=1;i<=n*2;i++)
        ans=ans*i*1LL%mod;
    printf("%lld\n",ans);
    return 0;
}

Measured memory_bytes: 62188