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
		}
	}

	// TODO: always start with 1?
	timer := 1
	visit(1, &timer, childrenMap, timeRecordMap)
	for k, v := range timeRecordMap {
		fmt.Printf("%d %d %d\n", k+1, v.discoverTime, v.finishTime)
	}
}

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: N = int(input())
edge = [[] for _ in range(N+1)]
d = [0] * (N+1)
f = [0] * (N+1)
for i in range(N):
    t = list(map(int, input().split()))
    for j in range(t[1]):
        edge[t[0]].append(t[j+2])

#print(1)
def dfs(v, t):
    if d[v] == 0:
        d[v] = t
        t += 1
    else:
        return t
    for nv in edge[v]:
        t = dfs(nv, t)
    if f[v] == 0:
        f[v] = t
        t += 1
    return t

t = 1
for i in range(1,1+N):
    if d[i] == 0:
        t = dfs(i, t)
for i in range(1,1+N):
    print(i, d[i], f[i])

Python: def dfs(u, node_info, matrix):
    # ????????????????????¨??????????????????
    colors = [0] * len(matrix)
    detect_time = [0] * len(matrix)
    finished_time = [0] * len(matrix)
    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 val == 1 and colors[i] == 0:
                time += 1
                print('stack: ', i)
                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]
    for i in range(len(matrix)):
        print('{} {} {}'.format(i + 1, detect_time[i], finished_time[i]))


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
    for line in matrix:
        print(line)
    dfs(0, None, matrix)

Python: n = int(input())

points = []
seen = []
find_time = []
end_time = []
for _ in range(n):
    input_text = list(map(int, input().split()))
    u, k, v_list = input_text[0], input_text[1], input_text[2:]
    seen.append(False)
    points.append(v_list)
    find_time.append(0)
    end_time.append(0)

count = [0]


def dfs(graph, v, count):
    seen[v] = True
    find_time[v] = count[0]
    for next_v in graph[v]:
        if seen[next_v - 1]:
            continue
        count[0] += 1
        dfs(graph, next_v - 1, count)
    count[0] += 1
    end_time[v] = count[0]


for index, seen_point in enumerate(seen):
    if seen_point:
        pass
    else:
        count[0] += 1
        dfs(points, index, count)
# print(find_time)
# print(end_time)


count = 1
for f, e in zip(find_time, end_time):
    print(count, f, e)
    count += 1

Python: # -*- coding: utf-8 -*-
"""
Created on Sun Jul  8 10:56:33 2018

@author: maezawa
"""
n = int(input())
adj = [[] for _ in range(n)]
d = [0 for _ in range(n)]
f = [0 for _ in range(n)]

for j in range(n):
    ain = list(map(int, input().split()))
    u = ain[0]
    k = ain[1]
    for i in range(k):
        adj[u-1].append(ain[i+2]-1)
    adj[u-1].sort()
    #print(*adj[u-1])

t = 1
stack = [0]

while stack:
    current = stack[-1]
    if d[current] == 0:
        d[current] = t
        t += 1
    flag = 0
    for k in adj[current]:
        if f[k] == 0:
            stack.append(k)
            flag = 1
            break
    if flag == 0:
        f[current] = t
        t += 1
        stack.pop()

    #print('current = {}, t = {}'.format(current, t))
    #print('stack', *stack)

for i in range(n):
    print('{} {} {}'.format(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
    dfs(1)
    for i in range(1, n + 1):
        print(" ".join(map(str, ans[i])))
MAIN()

Python: def inpl():
    return list(map(int, input().split()))


def dfs(v, step):
    if f[v] != -1:
        return step
    f[v] = step
    step += 1
    for nv in E[v]:
        # print("now", v, nv, step)
        step = dfs(nv - 1, step)
    d[v] = step
    return step + 1


n = int(input())
E = [[] for i in range(n)]
for _ in range(n):
    tmp = inpl()
    u, k = tmp[:2]
    E[u - 1] = tmp[2:]

d = [-1 for i in range(n)]
f = [-1 for i in range(n)]

step = 1
for v in range(n):
    step = dfs(v, step)

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

Python: n = int(input())
G = [[] for _ in range(n)]
u1 = 0
for _ in range(n):
    u, k, *v = [int(i) for i in input().split()]
    G[u - 1] = v
    if k != 0 and u1 == 0:
        u1 = u

time = 1
u = u1
D = []
F = []
out = [[i+1, 0, 0] for i in range(n)]
T = []
while True:
    if u not in D:
        out[u - 1][1] = time
        D.append(u)
        T.append(u)

    for f in F:
        if f in G[u - 1]:
            idx = G[u - 1].index(f)
            del G[u - 1][idx]

    if G[u - 1] == []:
        time += 1
        out[T.pop() - 1][2] = time
        F.append(u)
        if T == []:
            if len(D) == n:
                break
            else:
                for ni in range(n):
                    if ni + 1 not in D:
                        u = ni + 1
                        break
        else:
            u = T[-1]
    else:
        u = G[u - 1].pop(0)
        time += 1

for ni in range(n):
    print(*out[ni])

Python: count = 0


def solve(i, a, ans):
    global count
    if ans[i][0] == 0:
        count += 1
        ans[i][0] = count

    for x in range(a[i][1]):
        if ans[a[i][2 + x] - 1][0] == 0:
            solve(a[i][2 + x] - 1, a, ans)

    if ans[i][1] == 0:
        count += 1
        ans[i][1] = count


N = int(input())
a = []
for _ in range(N):
    a.append([int(x) for x in input().split()])

ans = [[0 for i in range(2)] for j in range(N)]

for i in range(N):
    if ans[i][0] == 0:
        solve(i, a, ans)

for i, x in enumerate(ans):
    print(i + 1, *x)