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) isVisited() bool {
	return v.firstVisitAt > 0
}

func dfs(currentId vertexId, timestamp int, vertices []vertex) int {
	currentVertex := &vertices[currentId-1]
	if currentVertex.isVisited() {
		return timestamp
	}
	timestamp = timestamp + 1
	currentVertex.firstVisitAt = timestamp
	for _, adjId := range currentVertex.adjs {
		timestamp = dfs(adjId, timestamp, vertices)
	}
	timestamp = timestamp + 1
	currentVertex.finishVisitAt = timestamp
	return timestamp
}

func solveDfs(vertices []vertex) {
	timestamp := 0
	for {
		vid := vertexId(-1)
		for i := 0; i < len(vertices); i++ {
			if !vertices[i].isVisited() {
				vid = vertexId(i+1)
				break
			}
		}
		if vid > 0 {
			timestamp = dfs(vid, timestamp, vertices)
		} else {
			break
		}
	}
}

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

	solveDfs(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: import collections,sys
def I(): return int(sys.stdin.readline().rstrip())
def LI(): return list(map(int,sys.stdin.readline().rstrip().split()))
n = I()
ukv = [LI() for _ in range(n)]
graph = {i:collections.deque() for i in range(1,n+1)} #1_indexed
for x in ukv:
    u,k,*v = x
    for y in v:
        graph[u].append(y)
seen = [0]*(n+1) #1_indexed
stack = []
time = 0
seentime = [0]*(n+1) #1_indexed
donetime = [0]*(n+1) #1_indexed
def dfs(j):
    global time
    seen[j] = 1
    stack.append(j)
    time += 1
    seentime[j] = time
    while stack:
        s = stack[-1]
        if not graph[s]:
            stack.pop()
            time += 1
            donetime[s] = time
            continue
        g_NO = graph[s].popleft()
        if seen[g_NO]:
            continue
        seen[g_NO] = 1
        stack.append(g_NO)
        time += 1
        seentime[g_NO] = time
for j in range(1,n+1):
    if seen[j]:
        continue
    dfs(j)
for k,a,b in zip(range(1,n+1),seentime[1:],donetime[1:]):
    print(k,a,b)

Python: def dfs(v, u=0):
    global n, t, d, f, reached
    if len(reached) == n:
        return

    d[u] = t
    t += 1

    reached.add(u + 1)
    for ui in range(v[u][1]):
        next = v[u][2 + ui]
        if next in reached:
            continue
        dfs(v, next - 1)

    f[u] = t
    t += 1


n = int(input())
v = []
for _ in range(n):
    v.append(list(map(int, input().split())))

t = 1
d = [0] * n
f = [0] * n
reached = set()


for ui in range(n):
    if ui + 1 not in reached:
        dfs(v, ui)

for ui in range(n):
    print('%d %d %d' % (ui + 1, d[ui], f[ui]))

Python: import sys

n = int(input())
G = [None]*(n+1)
for i in range(n):
    u, k, *vs = map(int, input().split())
    G[u] = vs

d = [-1]*(n+1)
f = [-1]*(n+1)
lb = iter(range(1, 2*n+1)).__next__
def dfs(v):
    d[v] = lb()
    for w in G[v]:
        if d[w] != -1: #already visited
            continue
        dfs(w)
    f[v] = lb()

for v in range(1, n+1):
    if d[v] != -1:
        continue
    dfs(v)

for v in range(1, n+1):
    print(f"{v} {d[v]} {f[v]}")

Python: 
d = None
f = None


def dfs(g, cur, time):
    global d, f
    d[cur] = time
    for next in g[cur]:
        if d[next] == 0:
            time = dfs(g, next, time+1)
    f[cur] = time + 1
    return time + 1


def main():
    global d, f
    n = int(input())
    g = [[] for _ in range(n)]
    d = [0 for _ in range(n)]
    f = [0 for _ in range(n)]
    for _ in range(n):
        inp = list(map(int, input().split()))
        m = inp[0] - 1
        k = inp[1]
        for i in range(k):
            g[m].append(inp[i+2] - 1)
    time = 1
    for i in range(n):
        if d[i] == 0:
            time = dfs(g, i, time) + 1
    for i in range(n):
        print(i+1, d[i], f[i])


if __name__ == '__main__':
    main()

Python: n = int(input())
trees = [[]]
for i in range(n):
    edges = []
    s = list(map(int, input().split()))
    num = s[1]
    if s[1] != 0:
        edges = s[2:2+num]
    trees.append(edges)

d = [0] * (n+1)
f = [0] * (n+1)


def dfs(x, i=0):
    for y in trees[x]:
        if d[y] != 0:
            continue
        d[y] = i
        i += 1
        i = dfs(y, i)
    f[x] = i
    i += 1
    return i


i = 1
for j in range(1, n+1):
    if d[j] != 0:
        continue
    else:
        d[j] = i
        i += 1
    i = dfs(j, i)
for i in range(1, n+1):
    print(i, d[i], f[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, d, f)

Python: import sys
input = sys.stdin.readline
d = []
f = []
time = 0
def search(r):
    global d,f,time,s
    if d[r] == 0:
        time += 1
        d[r] = time
    else:
        return
    for x in s[r]:
        search(x)
    time += 1
    f[r] = time


n = int(input())
s = [[] for i in range(n+1)]
for _ in range(n):
    d = list(map(int,input().split()))
    s[d[0]] = d[2:]

d = [0 for _ in range(n+1)]
f = [0 for _ in range(n+1)]

for i in range(1,n+1):
    if d[i] == 0:
        search(i)

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

Python: n = int(input()) # 点の総数
path = list() # path[p] : 点pから行ける点のリスト
path.append([])
for _ in range(n):
    tmp = list(map(int, input().split())) # tmp[0]から行ける点はtmp[1]個あり、それはtmp[2:]
    path.append(tmp[2:])

d = [0]*(n+1) # 最初に発見した時刻
f = [0]*(n+1) # 隣接リストを調べ終えた時刻

TIME = 0

def dfs(p, d, f):
    global TIME
    TIME += 1
    d[p] = TIME # 来訪時刻の記録

    for nxt in path[p]: #繋がってる点の内
        if d[nxt] == 0: # 未探索の場合には
            dfs(nxt, d, f) # 先に進む
    
    TIME += 1
    f[p] = TIME # 繋がってる全ての点を探索し終えたらその点でやることは終わり

    
    return     
    
for start in range(1, n+1):
    if d[start] == 0:
        dfs(start, d, f)

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