Depth-first search (DFS) follows the strategy to search ”deeper” in the graph whenever possible. In DFS, edges are recursively explored out of the most recently discovered vertex $v$ that still has unexplored edges leaving it. When all of $v$'s edges have been explored, the search ”backtracks” to explore edges leaving the vertex from which $v$ was discovered.

This process continues until all the vertices that are reachable from the original source vertex have been discovered. If any undiscovered vertices remain, then one of them is selected as a new source and the search is repeated from that source.

DFS timestamps each vertex as follows:

* $d[v]$ records when $v$ is first discovered.
* $f[v]$ records when the search finishes examining $v$’s adjacency list.



Write a program which reads a directed graph $G = (V, E)$ and demonstrates DFS on the graph based on the following rules:

* $G$ is given in an adjacency-list. Vertices are identified by IDs $1, 2,... n$ respectively.
* IDs in the adjacency list are arranged in ascending order.
* The program should report the discover time and the finish time for each vertex.
* When there are several candidates to visit during DFS, the algorithm should select the vertex with the smallest ID.
* The timestamp starts with 1.

Constraints

* $1 \leq n \leq 100$

Input

In the first line, an integer $n$ denoting the number of vertices of $G$ is given. In the next $n$ lines, adjacency lists of $u$ are given in the following format:

$u$ $k$ $v_1$ $v_2$ ... $v_k$

$u$ is ID of the vertex and $k$ denotes its degree. $v_i$ are IDs of vertices adjacent to $u$.

Output

For each vertex, print $id$, $d$ and $f$ separated by a space character in a line. $id$ is ID of the vertex, $d$ and $f$ is the discover time and the finish time respectively. Print in order of vertex IDs.

Examples

Input

4
1 1 2
2 1 4
3 0
4 1 3


Output

1 1 8
2 2 7
3 4 5
4 3 6


Input

6
1 2 2 3
2 2 3 4
3 1 5
4 1 6
5 1 6
6 0


Output

1 1 12
2 2 11
3 3 8
4 9 10
5 4 7
6 5 6
import java.io.*;
import java.util.*;


public class Main {

	private static Scanner sc;
	private static Printer pr;

	// AOJ ALDS1_11_B
	private static void solve() {
		int n = sc.nextInt();

		List<Set<Integer>> edges = new ArrayList<>(n);
		for (int i = 0; i < n; i++) {
			// スタックを使うため逆順に積んでいく
			edges.add(new TreeSet<>(Collections.reverseOrder()));

			int u = sc.nextInt() - 1;
			int k = sc.nextInt();
			for (int j = 0; j < k; j++) {
				int v = sc.nextInt() - 1;
				edges.get(u).add(v);
			}
		}

		int[] d = new int[n];
		int[] f = new int[n];
		int clock = 1;

		int[] used = new int[n];  // 0:White, 1:Gray, 2:Black
		for (int i = 0; i < n; i++) {
			if (used[i] != 0) {
				continue;
			}

			Deque<Integer> st = new ArrayDeque<>();
			st.push(i);
			while (!st.isEmpty()) {
				int e = st.peek();

				if (used[e] == 2) {
					st.pop();
				} else if (used[e] == 1) {
					used[e] = 2;
					f[e] = clock++;
					st.pop();
				} else {
					used[e] = 1;
					d[e] = clock++;
					for (int next : edges.get(e)) {
						if (used[next] == 2) {
							// 前進辺または横断辺
							continue;
						} else if (used[next] == 1) {
							// 後退辺
							continue;
						}

						st.push(next);
					}
				}
			}
		}

		for (int i = 0; i < n; i++) {
			pr.printf("%d %d %d\n", i + 1, d[i], f[i]);
		}
	}

	// ---------------------------------------------------
	public static void main(String[] args) {
		sc = new Scanner(INPUT == null ? System.in : new ByteArrayInputStream(INPUT.getBytes()));
		pr = new Printer(System.out);

		solve();

//		pr.close();
		pr.flush();
//		sc.close();
	}

	static String INPUT = null;

	@SuppressWarnings("unused")
	private static class Scanner {
		BufferedReader br;

		Scanner (InputStream in) {
			br = new BufferedReader(new InputStreamReader(in));
		}

		private boolean isPrintable(int ch) {
			return ch >= '!' && ch <= '~';
		}

		private boolean isCRLF(int ch) {
			return ch == '\n' || ch == '\r' || ch == -1;
		}

		private int nextPrintable() {
			try {
				int ch;
				while (!isPrintable(ch = br.read())) {
					if (ch == -1) {
						throw new NoSuchElementException();
					}
				}

				return ch;
			} catch (IOException e) {
				throw new NoSuchElementException();
			}
		}

		String next() {
			try {
				int ch = nextPrintable();
				StringBuilder sb = new StringBuilder();
				do {
					sb.appendCodePoint(ch);
				} while (isPrintable(ch = br.read()));

				return sb.toString();
			} catch (IOException e) {
				throw new NoSuchElementException();
			}
		}

		int nextInt() {
			try {
				// parseInt from Integer.parseInt()
				boolean negative = false;
				int res = 0;
				int limit = -Integer.MAX_VALUE;
				int radix = 10;

				int fc = nextPrintable();
				if (fc < '0') {
					if (fc == '-') {
						negative = true;
						limit = Integer.MIN_VALUE;
					} else if (fc != '+') {
						throw new NumberFormatException();
					}
					fc = br.read();
				}
				int multmin = limit / radix;

				int ch = fc;
				do {
					int digit = ch - '0';
					if (digit < 0 || digit >= radix) {
						throw new NumberFormatException();
					}
					if (res < multmin) {
						throw new NumberFormatException();
					}
					res *= radix;
					if (res < limit + digit) {
						throw new NumberFormatException();
					}
					res -= digit;

				} while (isPrintable(ch = br.read()));

				return negative ? res : -res;
			} catch (IOException e) {
				throw new NoSuchElementException();
			}
		}

		long nextLong() {
			try {
				// parseLong from Long.parseLong()
				boolean negative = false;
				long res = 0;
				long limit = -Long.MAX_VALUE;
				int radix = 10;

				int fc = nextPrintable();
				if (fc < '0') {
					if (fc == '-') {
						negative = true;
						limit = Long.MIN_VALUE;
					} else if (fc != '+') {
						throw new NumberFormatException();
					}
					fc = br.read();
				}
				long multmin = limit / radix;

				int ch = fc;
				do {
					int digit = ch - '0';
					if (digit < 0 || digit >= radix) {
						throw new NumberFormatException();
					}
					if (res < multmin) {
						throw new NumberFormatException();
					}
					res *= radix;
					if (res < limit + digit) {
						throw new NumberFormatException();
					}
					res -= digit;

				} while (isPrintable(ch = br.read()));

				return negative ? res : -res;
			} catch (IOException e) {
				throw new NoSuchElementException();
			}
		}

		float nextFloat() {
			return Float.parseFloat(next());
		}

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

		String nextLine() {
			try {
				int ch;
				while (isCRLF(ch = br.read())) {
					if (ch == -1) {
						throw new NoSuchElementException();
					}
				}
				StringBuilder sb = new StringBuilder();
				do {
					sb.appendCodePoint(ch);
				} while (!isCRLF(ch = br.read()));

				return sb.toString();
			} catch (IOException e) {
				throw new NoSuchElementException();
			}
		}

		void close() {
			try {
				br.close();
			} catch (IOException e) {
//				throw new NoSuchElementException();
			}
		}
	}

	private static class Printer extends PrintWriter {
		Printer(OutputStream out) {
			super(out);
		}
	}
}

