A new set of desks just arrived, and it's about time! Things were getting quite cramped in the office. You've been put in charge of creating a new seating chart for the engineers. The desks are numbered, and you sent out a survey to the engineering team asking each engineer the number of the desk they currently sit at, and the number of the desk they would like to sit at (which may be the same as their current desk). Each engineer must either remain where they sit, or move to the desired seat they indicated in the survey. No two engineers currently sit at the same desk, nor may any two engineers sit at the same desk in the new seating arrangement.

How many seating arrangements can you create that meet the specified requirements? The answer may be very large, so compute it modulo 1000000007 = 109 + 7.

Input

Input will begin with a line containing N (1 ≤ N ≤ 100000), the number of engineers. 

N lines follow, each containing exactly two integers. The i-th line contains the number of the current desk of the i-th engineer and the number of the desk the i-th engineer wants to move to. Desks are numbered from 1 to 2·N. It is guaranteed that no two engineers sit at the same desk.

Output

Print the number of possible assignments, modulo 1000000007 = 109 + 7.

Examples

Input

4
1 5
5 2
3 7
7 3


Output

6


Input

5
1 10
2 10
3 10
4 10
5 5


Output

5

Note

These are the possible assignments for the first example: 

  * 1 5 3 7 
  * 1 2 3 7 
  * 5 2 3 7 
  * 1 5 7 3 
  * 1 2 7 3 
  * 5 2 7 3 
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E859 {
	static class Solver {

		int N, indeg[], odeg[], seat[], to[], MOD = 1000000007;
		boolean vis[], cyc[], bad[], chill[], found;
		ArrayList<Integer>[] badj;

		int cycdfs(int n) {
			vis[n] = true;
			if (odeg[n] == 0) {
				chill[n] = true;
				return -1;
			}
			// this is an unvisited node
			int v = to[n];
			if (vis[v]) {
				if (bad[v] || cyc[v] || v == n) {
					bad[n] = true;
					return -2;
				} else if (odeg[v] == 0 || chill[v]) {
					chill[n] = true;
					return -1;
				}
				cyc[n] = true;
				found = true;
				return v;
			}
			int k = cycdfs(v);
			if (k == -2)
				bad[n] = true;
			else if (k == -1) {
				chill[n] = true;
				return -1;
			} else {
				cyc[n] = true;
				if (k == n)
					return -2;
			}
			return k;
		}

		int size(int n) {
			int res = 1;
			for (int i : badj[n])
				res += size(i);
			return res;
		}

		@SuppressWarnings("unchecked")
		void solve(FastScanner s, PrintWriter out) {
			N = s.nextInt();
			badj = new ArrayList[N * 2];
			for (int i = 0; i < 2 * N; i++)
				badj[i] = new ArrayList<>();

			seat = new int[N];
			indeg = new int[2 * N];
			odeg = new int[2 * N];
			to = new int[2 * N];
			vis = new boolean[2 * N];
			cyc = new boolean[2 * N];
			chill = new boolean[2 * N];
			bad = new boolean[2 * N];
			for (int i = 0; i < N; i++) {
				int u = s.nextInt() - 1, v = s.nextInt() - 1;
				indeg[v]++;
				odeg[u]++;
				seat[i] = u;
				to[u] = v;
				badj[v].add(u);
			}

			long tot = 1;
			for (int i = 0; i < N; i++) {
				int x = seat[i];
				if (!vis[x]) {
					found = false;
					cycdfs(x);
					if (found)
						tot = mul(tot, 2);
				}
			}

			for (int i = 0; i < 2 * N; i++)
				if (odeg[i] == 0 && indeg[i] > 0)
					tot = mul(tot, size(i));

			out.println(tot);

		}

		long mul(long a, long b) {
			return (a * b) % MOD;
		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static int min(int a, int b) {
		return a < b ? a : b;
	}

	static int max(int a, int b) {
		return a > b ? a : b;
	}

	static long min(long a, long b) {
		return a < b ? a : b;
	}

	static long max(long a, long b) {
		return a > b ? a : b;
	}

	static int swap(int a, int b) {
		return a;
	}

	static Object swap(Object a, Object b) {
		return a;
	}

	static String ts(Object... o) {
		return Arrays.deepToString(o);
	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		public FastScanner(File f) throws FileNotFoundException {
			this(new FileInputStream(f));
		}

		public FastScanner(String s) {
			this.stream = new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8));
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public long nextLong() {
			return Long.parseLong(next());
		}

		public double nextDouble() {
			return Double.parseDouble(next());
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

		// Jacob Garbage

		public int[] nextIntArray(int N) {
			int[] ret = new int[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextInt();
			return ret;
		}

		public int[][] next2DIntArray(int N, int M) {
			int[][] ret = new int[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextIntArray(M);
			return ret;
		}

		public long[] nextLongArray(int N) {
			long[] ret = new long[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextLong();
			return ret;
		}

		public long[][] next2DLongArray(int N, int M) {
			long[][] ret = new long[N][];
			for (int i = 0; i < N; i++)
				ret[i] = nextLongArray(M);
			return ret;
		}

		public double[] nextDoubleArray(int N) {
			double[] ret = new double[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDouble();
			return ret;
		}

		public double[][] next2DDoubleArray(int N, int M) {
			double[][] ret = new double[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDoubleArray(M);
			return ret;
		}

	}
}
