Go: package main

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

type vertexId int

type vertex struct {
	id vertexId
	firstVisitAt int
	finishVisitAt int
	adjs []vertexId
}

func createVertex(id int, adjsInt []int) vertex {
	adjs := make([]vertexId, len(adjsInt))
	for i := 0; i < len(adjs); i++ {
		adjs[i] = vertexId(adjsInt[i])
	}
	return vertex{
		id: vertexId(id),
		firstVisitAt: 0,
		finishVisitAt: 0,
		adjs: adjs,
	}
}

func (v *vertex) doesAllAdjsVisited(vertices []vertex) bool {
	for _, vId := range v.adjs {
		adj := vertices[vId-1]
		if !adj.isVisited() {
			return false
		}
	}
	return true
}

func (v *vertex) isFirstVisit() bool {
	return v.firstVisitAt == 0
}

func (v *vertex) isVisited() bool {
	return v.firstVisitAt > 0
}

func (v *vertex) nextVertex(vertices []vertex) (vertexId, error) {
	for _, vId := range v.adjs {
		adj := vertices[vId-1]
		if !adj.isVisited() {
			return vId, nil
		}
	}
	return vertexId(-1), fmt.Errorf("illegal")
}

func dfs(currentId vertexId, timestamp int, vertices []vertex) int {
	timestamp = timestamp + 1
	currentVertex := &vertices[currentId-1]
	if currentVertex.isFirstVisit() {
		currentVertex.firstVisitAt = timestamp
	}
	for !currentVertex.doesAllAdjsVisited(vertices) {
		nextVertexId, _ := currentVertex.nextVertex(vertices)
		timestamp = dfs(nextVertexId, timestamp, vertices)
	}
	timestamp = timestamp + 1
	currentVertex.finishVisitAt = timestamp
	return timestamp
}

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	n, err := nextInt(sc)
	if err != nil {
		panic(err)
	}

	vertices := make([]vertex, n)
	for i := 0; i < n; i++ {
		id, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjN, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjs := make([]int, adjN)
		for j := 0; j < adjN; j++ {
			adjId, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			adjs[j] = adjId
		}
		vertices[i] = createVertex(id, adjs)
	}

	dfs(vertexId(1), 0, vertices)

	for i := 0; i < n; i++ {
		fmt.Printf("%d %d %d\n", vertices[i].id, vertices[i].firstVisitAt, vertices[i].finishVisitAt)
	}
}

func nextText(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

func nextInt(sc *bufio.Scanner) (int, error) {
	return strconv.Atoi(nextText(sc))
}

Python: N = int(input())
adj_list = []
for _ in range(N):
    line = list(input().split(" "))
    adj_list.append([int(k) - 1 for k in line[2:]])

d = [-1 for _ in range(N)]
f = [-1 for _ in range(N)]
time = 1

visited = set()

def dfs(p):
    global time
    if p in visited:
        return

    d[p] = time
    time += 1
    visited.add(p)
    for ad in adj_list[p]:
        if ad not in visited:
            dfs(ad)
    f[p] = time
    time += 1

for i in range(N):
    dfs(i)

for i in range(N):
    print(f"{i + 1} {d[i]} {f[i]}")

Python: # coding: utf-8
# Your code here!

n = int(input())
M = []
for i in range(n):
    adj = list(map(int,input().split()))
    if adj[1] == 0:
        M += [[]]
    else:
        M += [adj[2:]]
time = 1
ans = [[j+1,0,0] for j in range(n)] # id d f

while True:
    for i in range(n):
        if ans[i][1] == 0:
            stack = [i]
            ans[i][1] = time
            time += 1
            break
        elif i == n-1:
            for k in range(n):
                print(*ans[k])
            exit()
    while stack != []:
        u = stack[-1]
        if M[u] != []:
            for i in range(len(M[u])):
                v = M[u][0]
                M[u].remove(v)
                if ans[v-1][1] == 0:
                    ans[v-1][1] = time
                    stack.append(v-1)
                    time += 1
                    break
        else:
            stack.pop()
            ans[u][2] = time
            time += 1

Python: n=int(input())
G=[]
for i in range(n):
    L=list(map(int,input().split()))
    G.append(L[2:])
    for j in range(len(G[-1])):
        G[-1][j]-=1

Forder=[-1]*n
Lorder=[-1]*n
ptr=1
def dfs(v):
    #print(v)
    #print(G[v])
    #print()
    global ptr

    Forder[v]=ptr
    ptr+=1

    for next in G[v]:
        if Forder[next]!=-1:
            continue
        dfs(next)
    
    Lorder[v]=ptr
    ptr+=1

#while True:
#    #print(Forder,Lorder)
#    for i in range(n):
#        if Forder[i]!=-1 and Lorder[i]!=-1:
#            pass
#        else:
#            dfs(i)
#            continue
#
#        if i==n-1:
#            break
#    else:
#        continue
#    break
#
#for i in range(n):
#    print(i+1,Forder[i],Lorder[i])

##########
for i in range(n):
    if Forder[i]==-1 or Lorder[i]==-1:
        dfs(i)

for i in range(n):
    print(i+1,Forder[i],Lorder[i])

Python: n = int(input())
Adj = [[0 for i in range(n)] for i in range(n)]
 
for i in range(n):
    u = list(map(int, input().split()))
    if u[1] > 0:
        for i in u[2: 2 + u[1]]:
            Adj[u[0] - 1][i - 1] = 1
 
color = [0] * n
d = [0] * n
f = [0] * n
time = 0
def dfs(u):
    global time
    color[u - 1] = 1
    time += 1
    d[u - 1] = time
    for i in range(1, n+1):
        if Adj[u - 1][i - 1] == 1 and color[i - 1] == 0:
            dfs(i)
    color[u - 1] = 2
    time += 1
    f[u - 1] = time

for i in range(1, n+1):
    if color[i-1] == 0:
        dfs(i)
for i in range(n):
    print("{} {} {}".format(i+1,d[i],f[i]))

Python: def dfs(u, colors, matrix, time, detect_time, finished_time):
    # ????????????????????¨??????????????????
    colors = colors
    detect_time = detect_time
    finished_time = finished_time
    time = time + 1
    stack = list()
    stack.append(u)
    colors[u] = 1
    detect_time[u] = time
    while len(stack):
        for i, val in enumerate(matrix[u]):
            if i == 2 and val == 1:
                print('tanaka')
            if val == 1 and colors[i] == 0:
                time += 1
                stack.append(i)
                colors[i] = 1
                detect_time[i] = time
                u = i
                break
        else:
            time += 1
            e = stack.pop()
            colors[e] = 2
            finished_time[e] = time
            if len(stack):
                u = stack[-1]
    return time


if __name__ == '__main__':
    N = int(input())
    matrix = [[0] * N for _ in range(N)]
    color = [0] * N
    for i in matrix:
        node_info = [int(i) for i in input().split()]
        node_i = node_info[0] - 1
        if not node_info[1] == 0:
            for i in node_info[2:]:
                matrix[node_i][i - 1] = 1
    colors = [0] * len(matrix)
    detect_time = [0] * len(matrix)
    finished_time = [0] * len(matrix)
    time = 0
    for i, val in enumerate(colors):
        if val == 0:
            time = dfs(i, colors, matrix, time, detect_time, finished_time)

    for i in range(len(matrix)):
        print('{} {} {}'.format(i + 1, detect_time[i], finished_time[i]))

Python: j = 1
def dfs(graph, start, result, visited=None):
    global j
    if visited == None:
        visited = []
    visited.append(start)
    result[start][1]  = j
    for next in graph[start][2:]:
        if next in visited:
            continue
        j += 1
        dfs(graph, next, result, visited)
    else:
        j += 1
        result[start][2] = j

n = int(input())
g = [[]]
r = [[i,0,0] for i in range(n + 1)]

for i in range(n):
    g.append(list(map(int, input().split())))
dfs(g,1,r)
for i in range(1,n+1):
    print(*r[i])

Python: def dfs(v, cnt):
    D[v] = cnt
    cnt += 1
    for c in edge[v]:
        if D[c] == -1:
            cnt = dfs(c, cnt)
    F[v] = cnt
    cnt += 1
    return cnt

V = int(input())
edge = [[] for _ in range(V)]
for _ in range(V):
    u, _, *v = map(lambda x: int(x)-1, input().split())
    edge[u] = sorted(v)
D, F = [-1] * V, [-1] * V
c = 1
for i in range(V):
    if D[i] == -1:
        c = dfs(i, c)
for i, (d, f) in enumerate(zip(D, F)):
    print(i+1, d, f)