Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

//util
var sc = bufio.NewScanner(os.Stdin)

func nextStr() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func printList(list []int) {
	n := len(list)
	buf := bufio.NewWriter(os.Stdout)
	for _, v := range list[0 : n-1] {
		buf.Write([]byte(fmt.Sprintf("%d ", v)))
	}
	buf.Write([]byte(fmt.Sprintf("%d\n", list[n-1])))
	buf.Flush()
}

func max(a, b int) int {
	if a > b {
		return a
	} else {
		return b
	}
}

func min(a, b int) int {
	if a > b {
		return b
	} else {
		return a
	}
}

//solve

const MAX = 100
const WHITE = 0
const GRAY = 1
const BLACK = 2

var time, n int

//隣接行列
var M [MAX][MAX]int

//d[i]: 最初にiを訪問した時刻。発見時刻
//f[i]: iの隣接リストを訪問し終えた時刻。完了時刻
var color, d, f [MAX]int

func dfs_visit(u int) {
	color[u] = GRAY
	time++
	d[u] = time
	//隣接を調べる
	for v := 0; v < n; v++ {
		if M[u][v] == 0 {
			continue
		}
		//隣接するvが、未訪問だった場合
		if color[v] == WHITE {
			dfs_visit(v)
		}
	}
	//訪問完了処理
	color[u] = BLACK
	time++
	f[u] = time
	//訪問完了
}

func dfs() {
	//初期化
	for u := 0; u < n; u++ {
		color[u] = WHITE
	}
	time = 0

	//未訪問のuを始点として、深さ優先探索
	for u := 0; u < n; u++ {

		if color[u] == WHITE {
			dfs_visit(u)
		}
	}

	for u := 0; u < n; u++ {
		fmt.Println(u+1, d[u], f[u])
	}
}

func main() {
	sc.Split(bufio.ScanWords)
	n = nextInt()
	for i := 0; i < n; i++ {
		u, k := nextInt(), nextInt()
		M[u-1][u-1] = 0

		//fmt.Println(u, k)
		if k > 0 {
			for j := 0; j < k; j++ {

				v := nextInt()
				M[u-1][v-1] = 1

			}
		}

	}

	dfs()

}

Python: from typing import List

def DFS(G: List[int]):
	global time
	time = 0
	n = len(G)
	for u in range(n):
		if color[u] == "WHITE":
			DFS_Visit(u)

def DFS_Visit(u: int):
	global time
	color[u] = "GRAY"
	time += 1
	d[u] = time
	for v in G[u]:
		if color[v] == "WHITE":
			pi[v] = u
			DFS_Visit(v)
	color[u] = "BLACK"
	time += 1
	f[u] = time


if __name__ == "__main__":
	n = int(input())
	G = []
	color = ["WHITE" for _ in range(n)]
	pi = [None for _ in range(n)]
	d = [0 for _ in range(n)]
	f = [0 for _ in range(n)]

	for _ in range(n):
		command = list(map(int, input().split()))
		G.append([x - 1 for x in command[2:]])
	DFS(G)
	for i in range(n):
		print(f"{i + 1} {d[i]} {f[i]}")

Python: def MAIN():
    n = int(input())
    ans = [[i, 0, 0] for i in range((n + 1))]
    G = [[] for _ in range((n + 1))]
    for _ in range(n):
        u, k, *v = map(int, input().split())
        G[u] = v
    cnt = 1
    def dfs(u):
        nonlocal ans
        if ans[u][1] != 0:
            return
        nonlocal cnt
        ans[u][1] = cnt
        cnt += 1
        for v in G[u]:
            dfs(v)
        ans[u][2] = cnt
        cnt += 1
    for i in range(1, n + 1):
        if ans[i][1] == 0:
            dfs(i)
    for i in range(1, n + 1):
        print(" ".join(map(str, ans[i])))
MAIN()

Python: from collections import deque


def dfs(root):
    global time
    stack.append(root)
    color[root] = 'gray'
    arrive[root] = time
    time += 1

    while len(stack) > 0:
        node = stack[-1]
        for next in range(n):
            if adjMat[node][next] == 1:
                if color[next] == 'white':
                    color[next] = 'gray'
                    arrive[next] = time
                    time += 1
                    stack.append(next)
                    break
        # In case there in no adjacent node whose color is white
        color[node] = 'black'
        finish[node] = time
        time += 1
        stack.pop()


n = int(input())

adjMat = [[0] * n for _ in range(n)]
color = ['white'] * n
stack = deque()
arrive = [0] * n
finish = [0] * n
time = 1

for _ in range(n):
    adj = list(map(int, input().split()))
    i = adj[0]
    v = adj[2:]
    for j in v:
        adjMat[i - 1][j - 1] = 1

for root in range(n):
    if color[root] == 'white':
        dfs(root)

for i in range(n):
    out = ''
    out += '{} {} {}'.format(i + 1, arrive[i], finish[i])
    print(out)

Python: # -*- coding: utf-8 -*-
"""
Created on Sat Apr  6 11:36:14 2019

@author: Yamazaki Kenichi
"""

n = int(input())
A = [[]]
A = A + [list(map(int,input().split())) for i in range(n)]

def dfs(k):
    global counta
    for i in range(A[k][1]):
        if T[A[k][i+2]][0] == -1:
            T[A[k][i+2]][0] = 0
            T[A[k][i+2]][1] = counta
            counta += 1
            dfs(A[k][i+2])
    T[k][2] = counta
    T[k][0] = 1
    counta += 1

T = [[-1,-1,-1] for i in range(n+1)]
counta = 1
for i in range(1,n+1):
    if T[i][0] == -1:
        T[A[i][0]][0],T[A[i][0]][1] = 0, counta
        counta += 1
        dfs(i)

for i in range(1,n+1):
    print(" ".join(map(str,[i,T[i][1],T[i][2]])))

Python: N = int(input())
Adj = [[0 for i in range(N)] for j in range(N)]

for i in range(N):
    u = list(map(int, input().split()))
    if u[1] > 0:
        for k in u[2: 2+u[1]]:
            Adj[u[0] - 1][k - 1] = 1
            
            
color = [0] * N #1: visited, 0: not visited, 2: completed
s = [0] * N # start
f = [0] * N # finish

time = 0

def DFS(u):
    global time
    color[u-1] = 1
    time += 1
    s[u-1] = time
    
    for i in range(1, N+1):
        if Adj[u-1][i-1] == 1 and color[i-1] == 0:
            DFS(i)
            
    color[u-1] = 2
    time += 1
    f[u-1] = time

for i in range(1, N+1):
    if color[i-1] == 0:
        DFS(i)
        
for i in range(N):
    print('{} {} {}'.format(i+1, s[i], f[i]))

Python: # ??????????????????????£?????????????deque??????????????????
from collections import deque


class Node:
    def __init__(self, no, childs):
        self.no = no
        self.childs = childs
        self.find_time = None
        self.finish_time = None
        self.visit = False


def get_node_index(nodes, no):
    for i in range(len(nodes)):
        if nodes[i].no == no:
            return i


def get_unvisited(visited, childs):

    if childs is None: return None

    for i in range(len(childs)):
        if childs[i] not in visited:
            return childs[i]


"""
Main??????????????????
"""
# Node??°?????????
N = int(input())

# Node??????????????????????????????
nodes = []

# Node??????????¨????
for i in range(N):
    j = list(map(int, input().split())) # ??\??????????§£
    no = j[0]                           # Node??????????????? [2 2 1 4] ->2?????????
    childNum = j[1]
    if childNum != 0:
        childs = j[2:]                  # ??????????´?????????? [2 2 1 4] ->[1,4]?????????
    else:
        childs = []                     # ??????????´?????????? [2 2 1 4] ->[1,4]?????????
    nodes.append(Node(no, childs))


# ??±???????????¢?´¢(DFS)?????????
total_time = 1   # ??¢?´¢??????
stack = deque() # ??¢?´¢???????´?????´?????????????
stack.appendleft(1)
no = get_node_index(nodes, stack[0])  # ?????¨??¢?´¢???????´???????
nodes[no].find_time = total_time
visited = []    # ??¢?´¢??????????´?????´??????????

while stack:
    no = get_node_index(nodes, stack[0])  # ?????¨??¢?´¢???????´???????
    total_time += 1  # ??¢?´¢??????+1
    visited.append(stack[0])              # ??¢?´¢??????????????????????´?
    # ?????¢?´¢???????´??????????
    unvisited = get_unvisited(visited, nodes[no].childs)
    if unvisited is not None:
        # ?????¢?´¢???????´??????????????????????????????¢?´¢????´????????????§??????????????????????????????????´???§????????´????????¢?´¢?????\?????????????????????
        if nodes[unvisited-1].visit is False:
            nodes[unvisited-1].visit = True
            stack.appendleft(unvisited)
            nodes[unvisited-1].find_time = total_time
    else:
        stack.popleft()
        nodes[no].finish_time = total_time



#??¨?????????
for i in range(N):
    print("{0} {1} {2}".format(nodes[i].no, nodes[i].find_time, nodes[i].finish_time))