Go: package main

/*
深さ優先探索
*/

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

func main() {
	scanner := makeScanner(8192)
	n := eGetInt(scanner)
	g := make([][]int, n+1)
	for i := 1; i < n+1; i++ {
		ints := eGetInts(scanner)
		num, vcount := ints[0], ints[1]
		g[i] = make([]int, vcount)
		for j := 0; j < vcount; j++ {
			g[num][j] = ints[j+2]
		}
	}
	hist := make([]struct{ d, f int }, n+1)
	t := 0
	var visit func(int)
	visit = func(num int) {
		if hist[num].d == 0 {
			stack := []int{}
			t++
			hist[num].d = t
			stack = append(stack, num)
			for len(stack) > 0 {
				// トップを訪問する
				top := stack[len(stack)-1]
				for i := 0; i < len(g[top]); i++ {
					if hist[g[top][i]].d == 0 {
						t++
						hist[g[top][i]].d = t
						stack = append(stack, g[top][i])
						goto endloop
					}
				}
				// 訪問場所がなくなったら
				// pop
				stack = stack[0 : len(stack)-1]
				t++
				hist[top].f = t
			endloop:
			}
		}
	}
	for i := 1; i < n+1; i++ {
		visit(i)
	}
	for i := 1; i < n+1; i++ {
		fmt.Println(i, hist[i].d, hist[i].f)
	}
}

////////////////////////////////////////////////////////////////////////////////
// ライブラリ
////////////////////////////////////////////////////////////////////////////////
func makeScanner(maxByte int) *bufio.Scanner {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Buffer(make([]uint8, 0, 8192), maxByte)
	return scanner
}
func makeWordScanner() *bufio.Scanner {
	scanner := makeScanner(8192)
	scanner.Split(bufio.ScanWords)
	return scanner
}
func eGetLine(r *bufio.Scanner) string {
	if r.Scan() {
		return r.Text()
	}
	err := r.Err()
	if err != nil {
		log.Fatal(err)
	}
	// EOF
	return ""
}
func eGetInt(r *bufio.Scanner) int {
	line := eGetLine(r)
	return eAtoi(line)
}
func eGetInt64(r *bufio.Scanner) int64 {
	line := eGetLine(r)
	return eAtoInt64(line)
}
func eGetFields(r *bufio.Scanner) []string {
	line := eGetLine(r)
	return strings.Fields(line)
}
func eGetInts(r *bufio.Scanner) []int {
	fields := eGetFields(r)
	ints := make([]int, len(fields))
	for i := 0; i < len(ints); i++ {
		ints[i] = eAtoi(fields[i])
	}
	return ints
}
func eGetInt64s(r *bufio.Scanner) []int64 {
	fields := eGetFields(r)
	ints := make([]int64, len(fields))
	for i := 0; i < len(ints); i++ {
		ints[i] = eAtoInt64(fields[i])
	}
	return ints
}
func eGetChars(r *bufio.Scanner) []string {
	line := eGetLine(r)
	return strings.Split(line, "")
}
func eAtoi(s string) int {
	n, err := strconv.Atoi(s)
	if err != nil {
		log.Fatal(err)
	}
	return n
}
func eAtoInt64(s string) int64 {
	n, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		log.Fatal(err)
	}
	return n
}

Python: # ALDS_11_B - 深さ優先探索
import sys

n = int(input())
e = [None] * n
for _ in range(n):
    u, k, *v = map(int, sys.stdin.readline().strip().split())
    e[u - 1] = [i - 1 for i in v]


S = []  # stack
time = 0
t_in = [0] * n
t_out = [0] * n
fp = [False] * n  # foot print  訪問の記録


def dfs(u):
    global time

    S.append(u)
    time += 1
    t_in[u] = time
    fp[u] = True

    while S:
        u = S[-1]

        v = None
        for i in e[u]:
            if fp[i] is False:
                v = i
                break

        time += 1
        if v is not None:
            S.append(v)
            t_in[v] = time
            fp[v] = True

        else:
            v = S.pop()
            t_out[v] = time


while False in fp:
    dfs(fp.index(False))

for i in range(n):
    print(f'{i + 1} {t_in[i]} {t_out[i]}')

Python: from sys import stdin
readline=stdin.readline

#入力
n=int(readline())
m=n+1
u,k,v=[0]*m,[0]*m,[0]*m
for i in range(1,m):
    u[i],k[i],*v[i]=map(int,readline().split())

d=[0]*m
f=[0]*m
flags=[False]*m
t=0
def dfs(now):
    global t
    t+=1
    d[now]=t
    flags[now]=True
    for nex in v[now]:
        if flags[nex]==False:
            dfs(nex)
    t+=1
    f[now]=t
now=1
while True:
    dfs(now)
    for i in range(1,m):
        if flags[i]==False:
            now=i
            break
    else:
        break

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

Python: n=0
t=1
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):
            d[i] = t
            t += 1
            for (j,x) in enumerate(array[i]):
                if x == 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)]
    dfs(array,0,d,f)
    for i in range(n):
        print("{} {} {}".format(i+1,d[i],f[i]))

if __name__ == "__main__":
    main()

Python: #coding:utf-8
from copy import deepcopy

n = int(input())
c = ["white" for i in range(n)]
d = [0 for i in range(n)]
f = [0 for i in range(n)]
S = []
class DFS:
    def __init__(self, key, color="white",nex=None):
        self.color = color
        self.nex = nex
        self.key = key

objListCopy = [DFS(i+1) for i in range(n)]
for i in range(n):
    data = list(map(int,input().split()))
    times = data[1]
    obj = objListCopy[i]
    for j in range(times):
        index = data[2+j] - 1
        nextobj = DFS(index+1)
        obj.nex = nextobj
        obj = obj.nex


time = 1
objList = objListCopy[:]
def check(first,time):
    obj = objList[first]
    c[first] = "gray"
    d[first] = time
    f[first] = time
    S.append(first+1)
    
    while S != []:
        index = S[-1] - 1
        u = objList[index]
        v = u.nex
        
        time += 1
        if v != None and c[v.key - 1] == "white":
            objList[index] = v
            index = v.key - 1
            v = objList[index]
            c[v.key-1] = "gray"
            d[index] = time
            S.append(v.key)

        elif v != None and c[v.key - 1] == "black" and v.nex != None:
            objList[index] = v
            time -= 1
            
        else:
            S.pop()
            c[u.key-1] = "black"
            f[index] = time
    return time


for i in range(n):
    if f[i] == 0:
        objList = deepcopy(objListCopy)
        time = check(i,time) + 1
        

k = 1
for i,j in zip(d,f):
    print(k,i,j)
    k += 1

Python: def solve(v, g, ans, time):
    if ans[v]["found"] != 10**9:
        return time
    time += 1
    # print(v + 1, time, file=sys.stderr)
    ans[v]["found"] = time
    for a in g[v]:
        time = solve(a, g, ans, time)
    time += 1
    # print(v + 1, time, file=sys.stderr)
    ans[v]["complete"] = time
    return time


def resolve():
    n = int(input())
    V = [list(map(int, input().split())) for _ in range(n)]
    g = [[] for _ in range(n)]
    for v, k, *a in V:
        v -= 1
        for ai in a:
            ai -= 1
            g[v].append(ai)
    ans = [{"found": 10**9, "complete": -1} for _ in range(n)]
    time = solve(0, g, ans, 0)
    for i in range(n):
        if ans[i]["found"] == 10**9:
            solve(i, g, ans, time)
        print(i + 1, ans[i]["found"], ans[i]["complete"])


resolve()

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

n = int(input())
M = [[False for i in range(n)] for j in range(n)]
WHITE = 0
GRAY = 1
BLACK = 2
color = [WHITE for i in range(n)]
d = [0 for i in range(n)]
f = [0 for i in range(n)]
t = 1
for i in range(n):
        a = list(map(int, input().split()))
        for j in range(a[1]):
            M[a[0] - 1][a[j + 2] - 1] = True
for u in range(n):
    if color[u] == WHITE:
        dfs_visit(u)
for u in range(n):
    print(str(u + 1), str(d[u]), str(f[u]), sep = " ")