Go: package main

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

type TimeRecord struct {
	discoverTime int
	finishTime   int
}

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	n, err := nextInt(sc)
	if err != nil {
		panic(err)
	}

	timeRecordMap := make([]TimeRecord, n)
	childrenMap := make([][]int, n)
	for i := 1; i <= n; i++ {
		node, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		timeRecordMap[node-1] = TimeRecord{-1, -1}

		childNum, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		childrenMap[node-1] = make([]int, childNum)
		for j := 0; j < childNum; j++ {
			child, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			childrenMap[node-1][j] = child
		}
	}

	timer := 1
	startNode := 1
	for {
		visit(startNode, &timer, childrenMap, timeRecordMap)
		startNode = findStartNode(childrenMap, timeRecordMap)
		if startNode < 0 {
			break
		}
	}
	for k, v := range timeRecordMap {
		fmt.Printf("%d %d %d\n", k+1, v.discoverTime, v.finishTime)
	}
}

func findStartNode(childrenMap [][]int, timeRecordMap []TimeRecord) int {
	x := -1
	for node, timeRecord := range timeRecordMap {
		if timeRecord.discoverTime < 0 {
			x = node + 1
			break
		}
	}
	return x
}

func visit(currentNode int, timer *int, childrenMap [][]int, timeRecordMap []TimeRecord) {
	if timeRecordMap[currentNode-1].discoverTime > 0 {
		return
	}
	children := childrenMap[currentNode-1]
	timeRecordMap[currentNode-1] = TimeRecord{*timer, timeRecordMap[currentNode-1].finishTime}
	(*timer)++
	for i := 0; i < len(children); i++ {
		visit(children[i], timer, childrenMap, timeRecordMap)
	}
	timeRecordMap[currentNode-1] = TimeRecord{timeRecordMap[currentNode-1].discoverTime, *timer}
	(*timer)++
}

func nextInt(sc *bufio.Scanner) (int, error) {
	sc.Scan()
	return strconv.Atoi(sc.Text())
}

Python: # coding: utf-8
# Your code here!

n = int(input())
M = []
for i in range(n):
    adj = list(map(int,input().split()))
    if adj[1] == 0:
        M += [[]]
    else:
        M += [adj[2:]]
time = 1
ans = [[j+1,0,0] for j in range(n)] # id d f

while True:
    for i in range(n):
        if ans[i][1] == 0:
            stack = [i]
            ans[i][1] = time
            time += 1
            break
        elif i == n-1:
            for k in range(n):
                print(*ans[k])
            exit()
    while stack != []:
        u = stack[-1]
        if M[u] != []:
            for i in range(len(M[u])):
                v = M[u][0]
                M[u].remove(v)
                if ans[v-1][1] == 0:
                    ans[v-1][1] = time
                    stack.append(v-1)
                    time += 1
                    break
        else:
            stack.pop()
            ans[u][2] = time
            time += 1

Python: n=int(input())
G=[]
for i in range(n):
    L=list(map(int,input().split()))
    G.append(L[2:])
    for j in range(len(G[-1])):
        G[-1][j]-=1

Forder=[-1]*n
Lorder=[-1]*n
ptr=1
def dfs(v):
    #print(v)
    #print(G[v])
    #print()
    global ptr

    Forder[v]=ptr
    ptr+=1

    for next in G[v]:
        if Forder[next]!=-1:
            continue
        dfs(next)
    
    Lorder[v]=ptr
    ptr+=1

#while True:
#    #print(Forder,Lorder)
#    for i in range(n):
#        if Forder[i]!=-1 and Lorder[i]!=-1:
#            pass
#        else:
#            dfs(i)
#            continue
#
#        if i==n-1:
#            break
#    else:
#        continue
#    break
#
#for i in range(n):
#    print(i+1,Forder[i],Lorder[i])

##########
for i in range(n):
    if Forder[i]==-1 or Lorder[i]==-1:
        dfs(i)

for i in range(n):
    print(i+1,Forder[i],Lorder[i])

Python: n = int(input())
Adj = [[0 for i in range(n)] for i in range(n)]
 
for i in range(n):
    u = list(map(int, input().split()))
    if u[1] > 0:
        for i in u[2: 2 + u[1]]:
            Adj[u[0] - 1][i - 1] = 1
 
color = [0] * n
d = [0] * n
f = [0] * n
time = 0
def dfs(u):
    global time
    color[u - 1] = 1
    time += 1
    d[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,d[i],f[i]))

Python: def dfs(u, colors, matrix, time, detect_time, finished_time):
    # ????????????????????¨??????????????????
    colors = colors
    detect_time = detect_time
    finished_time = finished_time
    time = time + 1
    stack = list()
    stack.append(u)
    colors[u] = 1
    detect_time[u] = time
    while len(stack):
        for i, val in enumerate(matrix[u]):
            if i == 2 and val == 1:
                print('tanaka')
            if val == 1 and colors[i] == 0:
                time += 1
                stack.append(i)
                colors[i] = 1
                detect_time[i] = time
                u = i
                break
        else:
            time += 1
            e = stack.pop()
            colors[e] = 2
            finished_time[e] = time
            if len(stack):
                u = stack[-1]
    return time


if __name__ == '__main__':
    N = int(input())
    matrix = [[0] * N for _ in range(N)]
    color = [0] * N
    for i in matrix:
        node_info = [int(i) for i in input().split()]
        node_i = node_info[0] - 1
        if not node_info[1] == 0:
            for i in node_info[2:]:
                matrix[node_i][i - 1] = 1
    colors = [0] * len(matrix)
    detect_time = [0] * len(matrix)
    finished_time = [0] * len(matrix)
    time = 0
    for i, val in enumerate(colors):
        if val == 0:
            time = dfs(i, colors, matrix, time, detect_time, finished_time)

    for i in range(len(matrix)):
        print('{} {} {}'.format(i + 1, detect_time[i], finished_time[i]))

Python: j = 1
def dfs(graph, start, result, visited=None):
    global j
    if visited == None:
        visited = []
    visited.append(start)
    result[start][1]  = j
    for next in graph[start][2:]:
        if next in visited:
            continue
        j += 1
        dfs(graph, next, result, visited)
    else:
        j += 1
        result[start][2] = j

n = int(input())
g = [[]]
r = [[i,0,0] for i in range(n + 1)]

for i in range(n):
    g.append(list(map(int, input().split())))
dfs(g,1,r)
for i in range(1,n+1):
    print(*r[i])

Python: def dfs(v, cnt):
    D[v] = cnt
    cnt += 1
    for c in edge[v]:
        if D[c] == -1:
            cnt = dfs(c, cnt)
    F[v] = cnt
    cnt += 1
    return cnt

V = int(input())
edge = [[] for _ in range(V)]
for _ in range(V):
    u, _, *v = map(lambda x: int(x)-1, input().split())
    edge[u] = sorted(v)
D, F = [-1] * V, [-1] * V
c = 1
for i in range(V):
    if D[i] == -1:
        c = dfs(i, c)
for i, (d, f) in enumerate(zip(D, F)):
    print(i+1, d, f)

Python: n = int(input())
Adj = [[0]]
for _ in range(n):
    Adj.append(list(map(int, input().split()))[2:])

visited = [False]*(n+1)
s = [0]*(n+1)
f = [0]*(n+1)
time = 0

def dfs(i):
    global time
    time += 1
    s[i] = time
    visited[i] = True
    for j in Adj[i]:
        if not visited[j]:
            dfs(j)
    time += 1
    f[i] = time

while not all(visited[1:]):
    i = visited[1:].index(False) + 1
    dfs(i)

for i in range(1, n+1):
    print(i,s[i], f[i])