Go: package main

import (
	"fmt"
)

func main() {
	var n int
	fmt.Scan(&n)
	g := make([][]int, n+1)
	for i := 0; i < n; i++ {
		var u,k int
		fmt.Scan(&u)
		fmt.Scan(&k)
		g[u] = make([]int, k)
		for j := 0; j < k; j++ {
			fmt.Scan(&g[u][j])
		}
	}

	d := make([]int, n+1)
	f := make([]int, n+1)
	dfs(&g, &d, &f, 1, 1)

	for i := 1; i <= n; i++ {
		fmt.Printf("%d %d %d\n", i, d[i], f[i])
	}
}

func dfs(g *[][]int, d *[]int, f *[]int, id int, t int) int {
	if (*d)[id] > 0 {
		return t
	}
	(*d)[id] = t
	t += 1
	for i := 0; i < len((*g)[id]); i++ {
		t = dfs(g, d, f, (*g)[id][i], t)
	}
	(*f)[id] = t
	return t+1
}

Python: import sys


def dfs(u):
    global time
    color[u] = "GRAY"
    time += 1
    d[u] = time
    for v in range(n):
        if M[u][v] and color[v] == "WHITE":
            dfs(v)
    color[u] = "BLACK"
    time += 1
    f[u] = time


if __name__ == "__main__":
    n = int(sys.stdin.readline())
    color = ["WHITE"] * n
    time = 0
    d = [-1] * n
    f = [-1] * n
    M = [[0] * n for i in range(n)]
    for inp in sys.stdin.readlines():
        inp = list(map(int, inp.split()))
        for i in inp[2:]:
            M[inp[0]-1][i-1] = 1
    dfs(0)
    for i in range(n):
        print(i+1, d[i], f[i])

Python: # https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/11/ALDS1_11_B

G = {}
d = {}
f = {}
used = set()
t = 1


def dfs(cur):
    global G, d, f, t

    used.add(cur)
    d[cur] = t

    for i in G[cur]:
        if i in used:
            continue
        t += 1
        dfs(i)
    t += 1
    f[cur] = t


if __name__ == "__main__":
    N = int(input())

    for _ in range(N):
        u, k, *V = list(map(int, input().split()))
        G[u] = V

    for i in range(1, N+1):
        if i not in used:
            dfs(i)
            t += 1

    for i in G.keys():
        print(i, d[i], f[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 = []
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)
    if G[u - 1] == [] or out[G[u - 1][0] - 1][2] != 0:
        if out[u - 1][2] == 0:
            out[u - 1][2] = time + 1
        if T == []:
            break
        else:
            u = T.pop()
    else:
        T.append(u)
        u = G[u - 1].pop(0)

    time += 1
for ni in range(n):
    print(*out[ni])

Python: from enum import Enum


class Dfs(object):
    """ Depth First Search """
    class Status(Enum):
        white = 1
        gray = 2
        black = 3

    def __init__(self, data):
        self.time = 0
        num_of_nodes = len(data)+1
        self.color = [Dfs.Status.white] * (num_of_nodes+1)
        self.S = []
        self.M = self._make_matrix(data)
        self.s_time = [0] * (len(data) + 1)
        self.f_time = [0] * (len(data) + 1)

    def _make_matrix(self, data):
        """ ??£??\??????????????? (M[i][j]?????¢??§??????????????????+1??????????????????????????????) """
        num = len(data)
        graph_table = [[0] * (num+1) for _ in range(num+1)]
        for d in data:
            node_id = d[0]
            num_of_e = d[1]
            for e in d[2:]:
                graph_table[node_id][e] = 1
        return graph_table

    def search(self, start):
        self.time += 1
        self.s_time[start] = self.time
        self.S.append(start)
        self.color[start] = Dfs.Status.gray

        while self.S:
            u = self.S[-1]
            v = self.next(u)
            if v != None:
                if self.color[v] == Dfs.Status.white:
                    self.color[v] = Dfs.Status.gray
                    self.time += 1
                    self.s_time[v] = self.time
                    self.S.append((v))
            else:
                self.S = self.S[:-1]
                self.color[u] = Dfs.Status.black
                self.time += 1
                self.f_time[u] = self.time

    def next(self, node):
        """ ?¬?????¨???????????±???????????????????????????????????????????????¨??????????????????????????????? """
        edges = self.M[node]
        for i in range(1, len(edges)):
            if edges[i] == 1:
                if self.color[i] == Dfs.Status.white:
                    return i
        return None

    def print(self):
        for r in self.M:
            print(*r)


if __name__ == '__main__':
    # ??????????????\???
    num = int(input())
    data = []
    for _ in range(num):
        data.append(list(map(int, input().split(' '))))

    # ???????????????
    d = Dfs(data)
    for i in range(1, num+1):
        if d.color[i] == Dfs.Status.white:
            d.search(i)

    # ???????????????
    for i in range(1, num+1):
        print('{0} {1} {2}'.format(i, d.s_time[i], d.f_time[i]))

Python: #!/usr/bin/env python
# -*- coding: utf-8 -*-

"""

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 sys

UNVISITED, VISITED_IN_STACK, POPPED_OUT = 0, 1, 2


def dfs(v_init):
    global timer

    # init the first node of overall graph iterations(times >= 1)
    stack = list()
    stack.append(v_init)
    d_time[v_init] += timer
    # init end

    while stack:
        current = stack[-1]
        v_table = adj_table[current]
        visited[current] = VISITED_IN_STACK
        # if adj is None, current's adj(s) have been all visited
        adj = v_table.pop() if v_table else None

        if adj:
            if visited[adj] is UNVISITED:
                visited[adj] = VISITED_IN_STACK
                timer += 1
                d_time[adj] += timer
                stack.append(adj)
        else:
            stack.pop()
            visited[current] = POPPED_OUT
            timer += 1
            f_time[current] += timer

    return None


def dfs_init():
    global timer
    for v in range(v_num):
        if visited[v + 1] == UNVISITED:
            dfs(v + 1)
            timer += 1


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    v_num = int(_input[0])
    vertices = map(lambda x: x.split(), _input[1:])

    # config length = (v_num + 1)
    # stack = []
    visited = [UNVISITED] * (v_num + 1)
    d_time, f_time = ([0] * (v_num + 1) for _ in range(2))
    adj_table = tuple([] for _ in range(v_num + 1))
    for v_info in vertices:
        v_index, adj_num, *adj_list = map(int, v_info)
        # assert len(adj_list) == adj_num
        adj_table[v_index].extend(sorted(adj_list, reverse=True))

    # timing start from 1
    timer = 0
    dfs_init()

    for index, time_info in enumerate(zip(d_time[1:], f_time[1:]), 1):
        print(index, *time_info)

Python: # -*- coding: utf-8 -*-

import sys
sys.setrecursionlimit(10 ** 9)
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
INF=float('inf')

N=INT()
nodes=[[] for i in range(N)]
for i in range(N):
    l=LIST()
    u=l[0]
    l=l[2:]
    for v in l:
        nodes[u-1].append(v-1)
    nodes[u-1].sort()

ans=[[0]*2 for i in range(N)]
visited=[False]*N
time=0
def rec(u):
    if visited[u]:
        return
    visited[u]=True
    global time
    time+=1
    ans[u][0]=time
    for v in nodes[u]:
        rec(v)
    time+=1
    ans[u][1]=time

rec(0)
for i in range(N):
    d,f=ans[i]
    print(i+1, d, f)