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: 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 = [[0 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 = [WHITE for i in range(n)]
d, f = [0 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: #深さ優先探索
import sys
input = sys.stdin.readline
from collections import deque

#グラフ作成(無向グラフでは#を消す)
N = int(input())
graph = [deque([]) for _ in range(N+1)]
for _ in range(N):
    u, k, *v = [int(x) for x in input().split()]
    v.sort()
    for i in v:
        graph[u].append(i)
        #graph[i].append(u)
        
time = 0
arrive_time = [-1] * (N+1) #到着時刻
finish_time = [-1] * (N+1) #終了時刻

def dfs(v):
    global time
    time += 1
    stack = [v]
    arrive_time[v] = time
    while stack:
        v = stack[-1]
        if graph[v]:
            w = graph[v].popleft()
            if arrive_time[w] < 0:
                time += 1
                arrive_time[w] = time
                stack.append(w)
        else:
            time += 1
            finish_time[v] = time
            stack.pop()
    return [arrive_time, finish_time]


# 孤立している頂点対策
for i in range(N):
    if arrive_time[i+1] < 0:
        ans = dfs(i+1)

# 頂点番号、発見時刻、完了時刻
for i in range(N):
    temp = [i + 1, ans[0][i+1], ans[1][i+1]]
    print(* temp)

Python: def main():
    """有向グラフの深さ優先探索
    
    Note: V[i]は頂点iから通じる頂点の集合を意味するが, 
             V[i]: {i}とV[i]: Noneは同値とされている。
    """
    stack = []
    passed_lines = []
    
    n = int(input())
    V = [None]*(n+1)
    D = [None]*(n+1)
    F = [None]*(n+1)
    passed_vertices = set()
    vertices = set(range(1, n+1))
    
    for i in range(1, n+1):
        _, _, *v = map(int, input().split())
        V[i] = set(v)

    i = 1
    time = 1
    stack.append(i)
    passed_vertices.add(i)
    D[i] = time
    while i <= n:
        new_vertices = list(V[i] - passed_vertices - {i})
        new_vertices.sort()
        if new_vertices:
            i = new_vertices[0]
            stack.append(i)
            time += 1
            if D[i] is None:
                D[i] = time
                passed_vertices.add(i)
            continue
        else:
            while stack:
                i = stack.pop()
                time += 1
                if list(V[i] - passed_vertices - {i}):
                    stack.append(i)
                    time -= 1
                    break
                if F[i] is None: 
                    F[i] = time
        if not list(V[i] - passed_vertices - {i}) and not stack:
            rest_vertices = list(vertices-passed_vertices)
            if rest_vertices:
                i = min(rest_vertices)
                stack.append(i)
                time += 1
                if D[i] is None:
                    D[i] = time
                    passed_vertices.add(i)
            else:
                break
    for id, d, f in zip(range(1, n+1), D[1:], F[1:]):
        print("{} {} {}".format(id, d, f))
        
if __name__ == "__main__":
    main()

Python: #coding:utf-8
        
def DFS(i,A,d,f,t):
    if d[i-1]:
        return t
    d[i-1]=t
    t+=1
    for j in A[i-1]:
        t=DFS(j,A,d,f,t)
    f[i-1]=t
    t+=1
    return t

if __name__=="__main__":
    n=int(input())
    A=[]
    for i in range(n):
        A.append(list(map(int,input().split(" ")))[2:])
    d=[0]*n
    f=[0]*n
    t=1
    for i in range(n):
        if d[i]==0:
            t=DFS(i+1,A,d,f,t)
    for i in range(n):
        print("{} {} {}".format(i+1,d[i],f[i]))

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

Python: n = int(input())
a = [None]
for i in range(n):
    adj = list(map(int,input().split()))
    a.append(adj[2:])
    
s = [None]
for i in range(1, n + 1):
    s.append([False, i])
    
time = 0

def dfs(u):
    global time
    s[u][0] = True
    time += 1
    s[u].append(time)
    
    for v in a[u]:
        if s[v][0] == False:
            dfs(v)
            
    time += 1
    s[u].append(time)
    
for i in range(1,n+1):
    if s[i][0] == False:
        dfs(i)
        
for x in s[1:]:
    print(*x[1:])

Python: from collections import deque

seen=[]
first_order =[]
last_order = []

def dfs(g, v, first_ptr, last_ptr):
    first_ptr=first_ptr+1
    last_ptr=first_ptr
    
    first_order[v] = first_ptr
    seen[v]=True 
    for next_v in g[v]:
        if seen[next_v]:
            continue
        first_ptr, last_ptr=dfs(g, next_v, first_ptr, last_ptr)
    last_ptr=last_ptr+1
    first_ptr=last_ptr

    last_order[v] = last_ptr
    return first_ptr, last_ptr

icase=1
if icase==0:
    n,m=map(int,input().split())
    g = [deque([]) for _ in range(n + 1)]
    for i in range(m):
        a,b=map(int,input().split())
        g[a].append(b)
#        g[b].append(a) # 無向グラフ
elif icase==1:        
    n=int(input())
    u=[0]*n
    k=[0]*n
#    v=[[] for i in range(n)]
    g = [deque([]) for _ in range(n + 1)]
    for i in range(n):
        ai=list(map(int,input().split()))
        u[i]=ai[0]
        k[i]=ai[1]
        g[i]=deque(ai[2:])
        for j in range(len(g[i])):
            g[i][j]-=1    
elif icase==2:
    n=6
    u=[1,2,3,4,5,6]
    k=[2,2,1,1,1,0]
    g = [deque([]) for _ in range(n + 1)]

    g[0]=deque([1,2])
    g[1]=deque([2,3])
    g[2]=deque([4])
    g[3]=deque([5])
    g[4]=deque([5])
    g[5]=deque([])
    g[5]=deque()

seen=[False]*n
first_ptr=0
last_ptr=0
first_order =[-1]*n
last_order = [-1]*n

for v in range(n):
    if seen[v]:
        continue
    else:
        first_ptr, last_ptr=dfs(g,v,first_ptr, last_ptr)

for v in range(n):
    print(v+1,first_order[v],last_order[v])

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()