#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=200005,mod=1e9+7;
using namespace std;
bool vis[N],instk[N],f,in_cir[N],r[N];
int n,top,val[N],par[N],size[N],p[N],inv[N];
template<typename T> inline bool chkmin(T a, T b) { return a > b ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T a, T b) { return a < b ? a = b, 1 : 0; }
struct Edge{
    int v, w;
    Edge() { }
    Edge(int v, int w) : v(v), w(w) { }
} ;
pair<int, int> stk[N];
vector<pair<int, int> > circle;
vector<int> node;
vector<Edge> g[N];
int ksm(int x,int y){
	int ans=1;
	for (;y;y>>=1,x=x*1ll*x%mod)
		if (y&1) ans=ans*1ll*x%mod;
	return ans;
}
int C(int x,int y){
	return p[x]*1ll*inv[y]%mod*inv[x-y]%mod;
}
void init(){
	p[0]=1;
	for (int i=1;i<=n;i++) p[i]=1ll*p[i-1]*1ll*i%mod;
	inv[n]=ksm(p[n],mod-2);
	for (int i=n;i>=1;i--) inv[i-1]=1ll*inv[i]*i%mod;
}
void dfs_circle(int x, int fa, int edge)
{
    if (f) return;
    stk[++top]=make_pair(x,edge);
    instk[x]=1;
    for (auto E:g[x]){
        int u=E.v, w=E.w;
        if (u==fa) continue;
        if (!instk[u]) dfs_circle(u,x,w);
        else{
            int t=u;
            do{
                u=stk[top].first;
                in_cir[u]=1;
                circle.push_back(stk[top--]);
            } while (u!=t);
            circle.back().second=w;
            f=1;
            return;
        }
        if (f) return;
    }
    instk[x] = 0;
    top--;
}

void dfs1(int x, int fa){
    vis[x]= 1;
    node.push_back(x);
    for (auto E:g[x]){
        int u=E.v, w=E.w;
        if (u!=fa and !in_cir[u]){
            val[u]=w;
            dfs1(u, x);
        }
    }
}

int dfs2(int x){
    int ret=1;
    for (auto E:g[x]){
        int u=E.v;
        if (par[u]!=x) continue;
        int t=dfs2(u);
		size[x]+=size[u];
        ret=1ll*ret*t%mod*C(size[x], size[u])%mod;
    }
    size[x]++;
    return ret;
}

int calc(){
    for (int u:node){
        size[u] = 0;
        par[u] = 0;
    }
    for (int u:node)
        for (auto E:g[u]){
            int v = E.v, w = E.w;
            if (w < val[u]) par[v] = u;
        }
    int SIZE = 0, ans = 1;
    for (int u:node)
        if (!par[u]){
            int t=dfs2(u);
			SIZE += size[u];
            ans=1ll*ans*t%mod*C(SIZE, size[u])%mod;
        }
    return ans;
}
int main() {
	scanf("%d",&n);
	n<<=1;
	init(); 
	int x,y;
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d",&x,&y);
        g[x].emplace_back(y+n/2,x+y);
        g[y+n/2].emplace_back(x,x+y);
        r[x]=r[y+n/2]=1;
    }
	int cnt=0;
    for (int i=1;i<=n;i++) cnt+=r[i];
    if (cnt!=n){
        puts("0");
        return 0;
    }
    int now=0,ans=1;
    for (int i = 1; i <= n && ans; ++i){
        if (!vis[i]){
            int cur=0;
            top=0;
            f=0;
            circle.clear();
            dfs_circle(i, 0, 0);
            node.clear();
            for (auto j:circle) dfs1(j.first, 0);
            for (auto j:circle) val[j.first]=j.second;
            cur=(cur+calc())%mod; 

            circle.push_back(circle[0]);
            for (int j=1;j<circle.size();++j)
                val[circle[j].first]=circle[j-1].second;
            cur=(cur+calc())%mod; 
			now+=node.size();
            ans=1ll*ans*cur%mod*C(now,node.size())%mod;
        }
    }
    printf("%d\n", ans);
    return 0;
}

Measured memory_bytes: 23928