#include <bits/stdc++.h>
using namespace std;
template <class X, class Y>
ostream& operator<<(ostream& os, const pair<X, Y>& p) {
  return os << "[" << p.first << ", " << p.second << "]";
}
template <class Ch, class Tr, class Container>
basic_ostream<Ch, Tr>& operator<<(basic_ostream<Ch, Tr>& os,
                                  const Container& x) {
  os << "{";
  bool f = 1;
  for (auto& y : x) {
    if (!f)
      os << ", ";
    else
      f = 0;
    os << y;
  }
  return os << "}";
}
struct Debug {
  template <class T>
  Debug& operator<<(const T& x) {
    return *this;
  }
};
const int N = 2e5 + 5, MOD = 1e9 + 7;
int occupied[N], want[N], vis[N], vid = 1;
vector<int> adj[N];
int dfs(int node) {
  vis[node] = 1;
  int ret = 1;
  for (int child : adj[node]) ret += dfs(child);
  return ret;
}
int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    int a, b;
    cin >> a >> b;
    want[a] = b;
    adj[b].push_back(a);
    occupied[a] = 1;
  }
  int ans = 1;
  for (int i = 1; i <= 2 * n; i++)
    if (!occupied[i]) ans = ans * 1ll * dfs(i) % MOD;
  for (int i = 1; i <= 2 * n; i++) {
    if (!occupied[i] || vis[i]) continue;
    ++vid;
    int cur = i;
    do {
      vis[cur] = vid;
      cur = want[cur];
    } while (!vis[cur]);
    if (vis[cur] == vid && want[cur] != cur) ans = ans * 2 % MOD;
  }
  cout << ans;
}
