Go: package main

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

var N int
var A [][]int
var t int
var color, d, f []int

const (
	WHITE = iota
	GRAY
	BLACK
)

func dfsVisit(u int) {
	color[u] = GRAY
	t ++
	d[u] = t
	for v:=0; v<N; v++ {
		if A[u][v] == 0 {
			continue
		}
		if color[v] == WHITE {
			dfsVisit(v)
		}
	}
	color[u] = BLACK
	t++
	f[u] = t
}

func dfs() {
	for u:=0; u<N; u++ {
		if color[u] == WHITE {
			dfsVisit(u)
		}
	}
	for u:=0; u<N; u++{
		fmt.Printf("%d %d %d\n", u+1, d[u], f[u])
	}
}


func nextInt(scanner *bufio.Scanner) int {
	scanner.Scan()
	num, _ := strconv.Atoi(scanner.Text())
	return num
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	N = nextInt(scanner)
	color = make([]int, N)
	d = make([]int, N)
	f = make([]int, N)
	A = make([][]int, N)
	for i:=0; i<N; i++{
		A[i] = make([]int, N)
	}
	for i:=0; i<N; i++{
		index := nextInt(scanner) - 1
		cnt := nextInt(scanner)
		for j:=0; j<cnt; j++ {
			v := nextInt(scanner) - 1
			A[index][v] = 1
		}
	}
	dfs()
}

Python: # 24
# ALDS_11_B - 深さ優先探索

from collections import deque

n = int(input())
u_l = []
k_l = []
v_l = []
for i in range(n):
    _in = input()
    _v_l = []
    for j,_ in enumerate(_in.split()):
        if j == 0:
            u_l.append(int(_))
        elif j == 1:
            k_l.append(int(_))
        else:
            _v_l.append(int(_))
    v_l.append(_v_l)

def dfs(v):
    global count
    c_l[v] = True
    d_l[v] = count
    count += 1
    for i in range(k_l[v]):
        _v = v_l[v][i]-1
        if not c_l[_v]:
            dfs(_v)
    f_l[v] = count
    count += 1

d_l = [None]*n
f_l = [None]*n
c_l = [False]*n
count = 1
while False in c_l:
    dfs(c_l.index(False))

for idx, d, f in zip(list(range(1,n+1)), d_l, f_l):
    print(idx, d, f)

Python: n=int(input())

l=[[0 for i in range(n)] for j in range(n)]##静的確保 隣接行列
d=[0 for i in range(n)]##発見
f=[0 for i in range(n)]##完了
stack=[]##スタック
check=[]

for i in range(n):
    p=[int(x) for x in input().split()]
    
    for j in range(n):
        if j+1 in p[2:]:
            l[i][j]=1
##print("---隣接行列---")
##print(l)

time=1
d[0]=1
stack+=[1]
check+=[-1]

while len(stack)!=0:
    ##print("----------while---------")
    for i in range(n):
        if l[stack[-1]-1][i]==1 and not i+1 in check:
            time+=1
            d[i]=time
            stack+=[i+1]

           ## print("stack:",stack)
           ## print("d[",i,"]:",d[i])
            break
        elif i==n-1:
##最深    
            check+=[stack[-1]]
            time+=1
            f[stack.pop()-1]=time

            ##print("f[",i,"]:",f[i])
            ##print("check:",check)
            


for i in range(n):
    print(i+1," ",d[i]," ",f[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 generate_adj_matrix(v_info):
    for v_detail in v_info:
        v_index, adj_num, *adj_list = map(int, v_detail)
        # assert len(adj_list) == adj_num
        init_adj_table[v_index].extend(sorted(adj_list, reverse=True))
    return init_adj_table


def graph_dfs(v_init):
    global time

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

    while len(stack) > 1:
        current = stack[-1]
        v_table = adj_table[current]
        adj = v_table.pop() if v_table else None

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

    return None


def dfs_start():
    global time
    for i in range(vertices_num):
        if color[i + 1] == UNVISITED:
            # print('round: ', i + 1)
            graph_dfs(i + 1)
            time += 1


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

    # config length = (vertex_num + 1)
    stack = [-1]
    color = [UNVISITED] * (vertices_num + 1)
    d_time, f_time = ([0] * (vertices_num + 1) for _ in range(2))

    adj_table = generate_adj_matrix(vertices_info)
    # timing start from 1
    time = 1
    dfs_start()
    for k, v in enumerate(zip(d_time[1:], f_time[1:]), 1):
        print(k, *v)

Python: def visit(u):
    global color, d, f, t
    color[u] = GRAY
    d[u] += t
    t += 1
    for v in range(n):
        if (M[u][v] == 0):
            continue
        else:
            if (color[v] == WHITE):
                visit(v)
    color[u] = BLACK
    f[u] = t
    t += 1

n = int(input())
M = [[False for i in range(n)] for i in range(n)]
for i in range(n):
    tmp = list(map(int, input().split()))
    for i in range(tmp[1]):
        M[tmp[0]-1][tmp[i+2]-1] = 1

WHITE = 0
GRAY = 1
BLACK = 2
color, d, f = [WHITE for i in range(n)]
t = 1
for u in range(n):
    if (color[u] == WHITE):
        visit(u)
for u in range(n):
    print(str(u+1), str(d[u]), str(f[u]), sep = " ")

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)