#include <bits/stdc++.h>
#pragma GCC optimize("O3")
using namespace std;
const int N = 500031;
int n;
int a[N], b[N];
int indeg[N], outdeg[N];
vector<int> g[N], gr[N];
int cnt;
int used[N];
bool is_loop(int v) {
  if (g[v].size() != 1) return false;
  return (g[v][0] == v);
}
void rdfs(int v) {
  used[v] = 1;
  cnt++;
  for (int i = 0; i < gr[v].size(); i++) {
    int to = gr[v][i];
    if (used[to]) continue;
    rdfs(to);
  }
}
void fill_dfs(int v) {
  used[v] = 1;
  for (int i = 0; i < g[v].size(); i++) {
    int to = g[v][i];
    if (used[to]) continue;
    fill_dfs(to);
  }
  for (int i = 0; i < gr[v].size(); i++) {
    int to = gr[v][i];
    if (used[to]) continue;
    fill_dfs(to);
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i] >> b[i];
    indeg[b[i]]++;
    outdeg[a[i]]++;
    g[a[i]].push_back(b[i]);
    gr[b[i]].push_back(a[i]);
  }
  long long ans = 1;
  for (int i = 1; i <= n * 2; i++) {
    if (outdeg[i] == 0) {
      cnt = 0;
      rdfs(i);
      ans *= cnt;
      ans %= 1000000007;
    }
  }
  for (int i = 1; i <= n * 2; i++) {
    if (used[i]) continue;
    if (is_loop(i)) fill_dfs(i);
  }
  for (int i = 1; i <= n * 2; i++) {
    if (used[i]) continue;
    fill_dfs(i);
    ans *= 2;
    ans %= 1000000007;
  }
  cout << ans << endl;
  cin.get();
  cin.get();
  return 0;
}
