Go: package main

import "fmt"

type node struct {
	id, d, v int
	adj      []node
}

var n int
var seen []bool
var graph []node

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

func dfs(v, t int) int {
	// fmt.Printf("dfs(v %d, t %d) en:\n", v, t)
	seen[v] = true
	graph[v].v = t
	tt := t
	for _, vv := range graph[v].adj {
		if !seen[vv.id] {
			tt = max(tt, dfs(vv.id, tt+1))
		}
	}
	graph[v].d = tt + 1
	// fmt.Printf("dfs(v %d, t %d) ex: d %d\n", v, t, graph[v].d)
	return graph[v].d
}

func main() {
	fmt.Scan(&n)
	graph = make([]node, n+1)
	for i := 1; i <= n; i++ {
		var u, k, v int
		fmt.Scan(&u, &k)
		graph[u].id = u
		// 頂点uはk個の隣接頂点を持っている
		for j := 0; j < k; j++ {
			fmt.Scan(&v)
			var t node
			t.id = v
			graph[u].adj = append(graph[u].adj, t)
		}
	}
	// fmt.Println("n", n, "graph", graph)
	seen = make([]bool, n+1)
	// t := dfs(1, 1)
	v, t := 1, 1
	done := false
	for !done {
		tt := dfs(v, t)
		done = true
		for i := range seen {
			if !seen[i] {
				done = false
				v = graph[i].id
				t = tt
				break
			}
		}
	}
	for i := 1; i <= n; i++ {
		fmt.Printf("%d %d %d\n", i, graph[i].v, graph[i].d)
	}
}

Python: from collections import deque
N=int(input())
color=["w"]*(N+1)
start=[None]*(N+1)
finish=[0]*(N+1)
rinsetu=[[] for i in range(N+1)]
for i in range(1,N+1):
    a=list(map(int,input().split()))
    a=a[2:]
    rinsetu[i]=a
def dfs(i,t):
    if color[i]=="w":
        t+=1
        start[i]=t
        color[i]="g"
        for j in rinsetu[i]:
            t=dfs(j,t)
        t+=1
        finish[i]=t
        return t
    else:return t
t=dfs(1,0)
while(None in start[1:]):
    a=start[1:].index(None)
    t=dfs(a+1,t)

for i in range(1,N+1):
    print("%d %d %d" %(i,start[i],finish[i]))

Python: from enum import Enum, auto

class Color(Enum):
    WHITE = auto() # 未訪問の頂点
    GRAY = auto() # 訪問済みだが, 全ての接点の調査は済んでいない状態の接点
    BLACK = auto() # 訪問, 調査済みの接点

n = int(input())
d = [0 for i in range(n)]
f = [0 for i in range(n)]

colors = [] # 頂点の訪問状態
A = [[0 for j in range(n)] for i in range(n)] # 隣接行列
# stack = [] ## スタックによる実装では頂点の保持が必要 => 再帰によって実装

# 隣接行列の初期化
for i in range(n):
    arr = list(map(int, input().split(' ')))
    u, k, v = arr[0], arr[1], arr[2:]
    for j in range(k):
        A[u-1][v[j]-1] = 1

time = 0
def dfs_init():
    global colors
    colors = [Color.WHITE for i in range(n)]
    dfs(0)

def dfs(u):
    global time
    colors[u] = Color.GRAY
    time += 1
    d[u] = time
    for v in range(n):
        if A[u][v] == 1 and colors[v] == Color.WHITE:
            dfs(v)
    colors[u] = Color.BLACK
    time += 1
    f[u] = time

dfs_init()

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

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

import sys

WHITE, GRAY, BLACK = 0, 1, 2


def generate_adj(v_info):
    for v_detail in v_info:
        v_adj_list = v_detail[2:]
        assert len(v_adj_list) == int(v_detail[1])
        for each in v_adj_list:
            init_adj_matrix[int(v_detail[0]) - 1][int(each) - 1] = 1
    return init_adj_matrix


def graph_dfs(start_node_index):
    # init the first node
    v_index = int(start_node_index)
    vertex_visit_stack.append(v_index)
    vertex_color_list[v_index] = GRAY
    time = 1
    vertex_d_time[v_index] += time
    # init end
    while len(vertex_visit_stack) > 1:
        current_vertex = vertex_visit_stack[-1]
        try:
            next_vertex = adj_matrix[current_vertex - 1].index(1) + 1
        except ValueError:
            # print('err')
            vertex_visit_stack.pop()
            vertex_color_list[current_vertex] = BLACK
            time += 1
            vertex_f_time[current_vertex] += time
        else:
            if vertex_color_list[next_vertex] == WHITE:
                # print('w2g', current_vertex, next_vertex, vertex_color_list[next_vertex])
                vertex_color_list[next_vertex] = GRAY
                time += 1
                vertex_d_time[next_vertex] += time
                vertex_visit_stack.append(next_vertex)
                # node A to B only visit once
                adj_matrix[current_vertex - 1][next_vertex - 1] = 0
            else:
                time += 1
                vertex_f_time[current_vertex] += time
                vertex_visit_stack.pop()
    return None


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertex_num = int(_input[0])
    vertex_info = list(map(lambda x: x.split(), _input[1:]))
    init_adj_matrix = [[0] * vertex_num for _ in range(vertex_num)]
    # assert len(vertex_info) == vertex_num

    vertex_visit_stack = [-1]
    vertex_color_list = [WHITE] * (vertex_num + 1)
    vertex_d_time, vertex_f_time = [0] * (vertex_num + 1), [0] * (vertex_num + 1)
    adj_matrix = generate_adj(vertex_info)

    graph_dfs(start_node_index=1)
    for i in range(vertex_num):
        print(i + 1, vertex_d_time[i + 1], vertex_f_time[i + 1])

Python: from sys import stdin
n = int(stdin.readline())
M = [None]
M += [list(map(int, stdin.readline().split()[2:])) for i in range(n)]
sndf = [None]
sndf += [[False, i] for i in range(1, n + 1)]
tt = 0
def dfs(u):
    global tt
    sndf[u][0] = True
    tt += 1
    sndf[u].append(tt)
    for v in M[u]:
        if not sndf[v][0]:
            dfs(v)
    tt += 1
    sndf[u].append(tt)
for i in range(1, n + 1):
    if not sndf[i][0]:
        dfs(i)
for x in sndf[1:]:
    print(*x[1:])

Python: n=0
t=2
def adjacent_matrix():
    global n
    n=int(input())
    v=[]
    array=[]
    for i in range(n):
        zero=[0 for i in range(n)]
        a=list(map(int,input().split()))
        a=a[2:]
        for j in a:
            zero[j-1]=1
        array.append(zero)
    return array
def dfs(array,i,d,f):
    global t
    if i == n:
        return
    else:
        if(d[i] == 0):
            for (j,x) in enumerate(array[i]):
                if x == 1:
                    d[j] = t
                    t += 1
                    dfs(array,j,d,f)
            f[i] = t
            t += 1
    return dfs(array,i+1,d,f)


def main():
    array=adjacent_matrix()
    print()
    d=[0 for i in range(n)]
    f=[0 for i in range(n)]
    d[0]=1
    f[0]=1
    dfs(array,0,d,f)
    for i in range(n):
        print("{} {} {}".format(i+1,d[i],f[i]))

if __name__ == "__main__":
    main()

Python: n = int(raw_input())

d = [0 for i in range(n)]
f = [0 for i in range(n)]
a = [[0 for i in range(n)] for j in range(n)]
st = [0 for i in range(n)]
time = [0]

def dfs_visit(s):
    st[s] = 1
    time[0] += 1
    d[s] = time[0]
    
    for k in range(n):  
      if a[s][k] == 1 and st[k] == 0:
          dfs_visit(k)
    time[0] += 1
    f[s] = time[0]

def main():
    for s in range(n):
        if st[s] == 0:
            def_visit(s)
    for s in range(n):
        print(s+1,d[s],f[s])

Python: def d(u):
 global t
 C[u]=1;t+=1;D[u]=t
 for v in range(N):
  if M[u][v]and C[v]==0:d(v)
 C[u]=2;t+=1;F[u]=t
N=int(input())
M=[[0]*N for _ in[0]*N]
for e in[list(map(int,input().split()))for _ in[0]*N]:
 for v in e[2:]:M[e[0]-1][v-1]=1
C,D,F=[0]*N,[0]*N,[0]*N
t=0
for i in range(N):
 if C[i]==0:d(i)
for i in range(N):print(i+1,D[i],F[i])