#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1000000 + 10;
const int MOD = 1000000007;

inline int inc(int a, int b) { return (a + b >= MOD) ? (a + b - MOD) : (a + b); }
inline int dec(int a, int b) { return (a >= b) ? (a - b) : (a + MOD - b); }
inline int mul(int a, int b) { return 1LL * a * b % MOD; }

inline int power(int x, int k) {
  int tmp = 1;
  while(k) {
    if(k & 1) tmp = mul(tmp,x);
    x = mul(x,x);
    k >>= 1;
	}
	return tmp;
}

int n, fac[maxn << 1], invfac[maxn << 1], inv[maxn << 1];
struct enode{
  int v, n;
  enode() {}
  enode(int _v, int _n):v(_v), n(_n) {}
};

namespace topo{

vector<int> g[maxn << 1], p;
int d[maxn << 1], vis[maxn << 1], sz[maxn];

inline void init() {
  p.clear();
  memset(d,0,sizeof(d));
}

inline void addedge(int u, int v) { g[u].push_back(v); d[v] ++; }

int dfs(int u, int fa) {
	vis[u] = 1;
	int tmp = 1, Sz = g[u].size(); sz[u] = 1;
  for(int i = 0;i < Sz;i ++) {
    int v = g[u][i];
    if(v == fa || vis[v]) continue;
    int now = dfs(v,u);
    tmp = mul(tmp,now);
    sz[u] += sz[v];
	}
	tmp = mul(tmp,inv[sz[u]]);
	return tmp;
}

inline int solve() {
	int k = -1;
	int Sz = p.size();
	int Ans = 1;
	for(int i = 0;i < Sz;i ++) {
		int u = p[i];
	  if(!d[u] && !vis[u]) {
	  	int tmp = dfs(u,0);
		  Ans = mul(Ans,tmp);
		}
	}
	for(int i = 0;i < Sz;i ++) {
	  int u = p[i];
	  d[u] = vis[u] = 0;
	  g[u].clear();
	}
	return Ans;
}

}

namespace g{

int h[maxn << 1], cnt, vis[maxn << 1];
int Ecnt, Pcnt, found, in[maxn << 1], cir[maxn << 1], stk[maxn << 1], top;
int bl[maxn << 1];
enode e[maxn << 2];

inline void init() {
  cnt = 0;
  memset(in,0,sizeof(in));
  memset(h,-1,sizeof(h));
  memset(vis,0,sizeof(vis));
}

inline void addedge(int u, int v) {
//	cout << "g " << u << ' ' << v << endl;
  cnt ++; e[cnt] = enode(v,h[u]); h[u] = cnt;
}

void dfs(int u, int fa) {
	Pcnt ++; 
	vis[u] = 1;
	stk[++ top] = u;
  for(int i = h[u];~ i;i = e[i].n) {
    int v = e[i].v, p;
    if(v == fa || in[v]) continue;
//    cout << "E " << u << ' ' << v << endl;
    Ecnt ++;
    if(!found && vis[v]) {
    	while(stk[top] != v) {
    	  p = stk[top --];
    	  in[p] = 1;
    	  cir[++ cir[0]] = p;
			}
			p = stk[top --];
			in[p] = 1;
			cir[++ cir[0]] = p;
			found = 1;
    }
    if(!vis[v]) dfs(v,u);
	}
	if(top && stk[top] == u) top --;
}

void dfs1(int u, int fa) {
  for(int i = h[u];~ i;i = e[i].n) {
    int v = e[i].v;
    if(v == fa || in[v]) continue;
    bl[v] = u;
    dfs1(v,u);
	}
}

void dfs2(int u, int fa) {
  int ch = bl[u];
  topo::p.push_back(u);
  for(int i = h[u];~ i;i = e[i].n) {
    int v = e[i].v;
    if(v >= ch) continue;
    topo::addedge(u,v);
	}
	for(int i = h[u];~ i;i = e[i].n) {
	  int v = e[i].v;
	  if(v == fa || in[v]) continue;
	  dfs2(v,u);
	}
}

inline int work(int u) {
	Ecnt = 0; Pcnt = 0;
	cir[0] = 0; top = 0;
	found = 0;
	dfs(u,0);
	if(Pcnt != Ecnt) return 0;
	for(int i = 1;i <= cir[0];i ++) {
	  dfs1(cir[i],0);
	}
	int tmp = 0;
	//1
	topo::init();
	for(int i = 1;i <= cir[0];i ++) {
	  int u = cir[i];
	  int v = cir[i % cir[0] + 1];
	  bl[u] = v;
	}
	for(int i = 1;i <= cir[0];i ++) 
	  dfs2(cir[i],0);
	tmp = inc(tmp,topo::solve());
	
	//2
	topo::init();
	for(int i = 1;i <= cir[0];i ++) {
	  int u = cir[i];
	  int v = cir[i % cir[0] + 1];
	  bl[v] = u;
	}
	for(int i = 1;i <= cir[0];i ++)
	  dfs2(cir[i],0);
	tmp = inc(tmp,topo::solve());
	return tmp;
}

inline void solve() {
	int Ans = 1;
	for(int i = 1;i <= n;i ++) {
	  if(!vis[i]) {
	  	int tmp = work(i);
	  	if(!tmp) {
	  	  puts("0");
	  	  return;
			}
			Ans = mul(Ans,tmp);
		}
	}
	Ans = mul(Ans,fac[n]);
	printf("%d\n", Ans);
}

}

inline void prepare(int n) {
  fac[0] = 1; invfac[0] = 1;
  for(int i = 1;i <= n;i ++) fac[i] = mul(fac[i - 1],i);
  invfac[n] = power(fac[n],MOD - 2);
  for(int i = n - 1;i >= 1;i --) invfac[i] = mul(i + 1,invfac[i + 1]);
  inv[0] = 1; inv[1] = 1;
  for(int i = 2;i <= n;i ++) inv[i] = mul(dec(MOD,MOD / i),inv[MOD % i]);
}

int main() {
	scanf("%d", &n);
	prepare(2000000);
	g::init();
	topo::init();
	for(int i = 1;i <= 2 * n;i ++) {
	  int x, y;
	  scanf("%d%d", &x, &y);
	  g::addedge(x,y + n);
	  g::addedge(y + n,x);
	}
	n <<= 1;
	g::solve();
  return 0;
}

Measured memory_bytes: 125428