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: # -*- coding: utf-8 -*-


class Graph:
    def __init__(self, n, adj_matrix):
        self.n = n
        self.g = adj_matrix

    def show(self):
        for _ in self.g:
            print(*_)

    def dfs(self, u, init=False):
        if init:
            self.states = [1] * self.n
            self.stack = []
            self.d = [None] * self.n
            self.f = [None] * self.n
            self.time = 0

        self.states[u] = 0
        self.time += 1
        self.d[u] = self.time

        for v, edge in enumerate(self.g[u]):
            if edge and self.states[v]:
                self.dfs(v)

        self.states[u] = 0
        self.time += 1
        self.f[u] = self.time

    def show_dfs(self, start=0):
        self.dfs(u=start, init=True)
        for i, (d, f) in enumerate(zip(self.d, self.f)):
            print(i + 1, d, f)


if __name__ == '__main__':
    n = int(input())
    adj_matrix = [[0] * n for i in range(n)]
    for i in range(n):
        for v in input().split()[2:]:
            adj_matrix[i][int(v) - 1] = 1

    g = Graph(n, adj_matrix)
    g.show_dfs()

Python: def srch(u, cnt, Dst, Fst, Lst):
    S = [u]
    Fst[u] = cnt
    while(len(S) > 0):
        cnt += 1
        u = S.pop()
        if Dst[u] is not None and len(Dst[u]) > 0:
            while(len(Dst[u])):
                u1 = Dst[u].pop()
                if Fst[u1] == 0:
                    S.append(u)
                    S.append(u1)
                    Fst[u1] = cnt
                    break
                else:
                    Lst[u] = cnt
        else:
            Lst[u] = cnt
    return cnt + 1

def main():
    num = int(input())
    Dst = [None for i in range(num + 1)]
    Fst = [0] * (num + 1)
    Lst = Fst[:]

    for n in range(1, num+1):
        a = list(map(int,input().split()))
        u = a[0]
        if a[1] > 0:
            Dst[u] = a[2:]
            Dst[u].reverse()

    cnt = 1
    for i in range(1,num):
        if Fst[i] == 0:
            cnt = srch(i, cnt, Dst, Fst, Lst)

    for n in range(1, num+1):
        print("{} {} {}".format(n,Fst[n],Lst[n]))

if __name__ == '__main__':
    main()

Python: from sys import stdin
n = int(stdin.readline())
M = [None] + [list(map(int, stdin.readline().split()[2:])) for i in range(n)]
sndf = [None] + [[False, i] for i in range(1, n + 1)]
tt = 0
def dfs(u):
    global tt
    sndf[u][0] = True
    tt += 1
    sndf[u].append(tt)
    for v in M[u]:
        if not sndf[v][0]:
            dfs(v)
    tt += 1
    sndf[u].append(tt)
for i in range(1, n + 1):
    if not sndf[i][0]:
        dfs(i)
    print(*sndf[i][1:])

Python: def main():
    n=int(input())
    u,k,v=0,0,[[] for _ in range(n+1)]
    for i in range(n):
        l=list(map(int,input().split()))
        u=l[0]
        for j in l[2:]:
            v[u].append(j)
    d=[0]*(n+1)
    f=[0]*(n+1)

    def dfs(s,t):
        d[s]=t
        for i in v[s]:
            if d[i]==0:
                t=dfs(i,t+1)
        f[s]=t+1
        return t+1

    s,t=1,1
    while 0 in d[1:]:
        T=dfs(s,t)
        for i in range(1,n+1):
            if d[i]==0:
                s=i
                t=T+1
                break

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

if __name__ == '__main__':
    main()

Python: import sys
sys.setrecursionlimit(10000000)
n = int(input())
G = [[] for i in range(n)]
d = [0 for i in range(n)]
f = [0 for i in range(n)]
color = [0 for i in range(n)]
stamp = 0

def dfs(u):
    global stamp
    if d[u]:
        return
    stamp += 1
    d[u] = stamp
    for v in G[u]:
        if color[v] != 0:
            continue
        color[v] = 1
        dfs(v)
    color[u] = 2
    stamp += 1
    f[u] = stamp

color[0] = 1
for i in range(n):
    inp = list(map(int, input().split()))
    u = inp[0]
    u -= 1
    k = inp[1]
    for j in range(k):
        v = inp[j+2]
        v -= 1
        G[u].append(v)
        #G[v].append(u)


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

for i in range(n):
    print("{0} {1} {2}".format(i+1, d[i], f[i]))

Python: """Depth First Search."""

n = int(input())

adj = [None]
for i in range(n):
    adj_i = list(map(int, input().split()[2:]))
    adj.append(adj_i)

# searched or not, number of vertex, discovery time and finishing time.
sndf = [None]
for i in range(1, n + 1):
    sndf.append([False, i])

path = []

time = 0

def dfs(u):
    global time
    path.append(u)
    sndf[u][0] = True
    time += 1
    sndf[u].append(time)

    while path:
        u = path[-1]
        if adj[u]:
            v = adj[u].pop(0)
            if not sndf[v][0]:
                sndf[v][0] = True
                time += 1
                sndf[v].append(time)
                path.append(v)
        else:
            path.pop()
            sndf[u][0] = True
            time += 1
            sndf[u].append(time)


for i in range(1, n + 1):
    if not sndf[i][0]:
        dfs(i)

for x in sndf[1:]:
    print(*x[1:])

Python: def curserch(N,k,t,P,n):
    g = 0
    t = t+1
    P[k]["d"] = t
    for i in range(1,n+1):
        if N[k][i]==1 and P[i]["d"]==0:
            P[i]["f"] = g = curserch(N,i,t,P,n)
    if g !=0:
        return g+1
    else:
        return t+1

n = int(input())
A = [[0 for j in range(n+1)] for i in range(n+1)]


for i in range(n):
    vec = input().split()
    u = int(vec[0])
    k = int(vec[1])
    nodes = vec[2:]
    for i in range(int(k)):
        v = int(nodes[i])
        A[u][v] = 1

P=[{"d":0} for i in range(n+1)]
P[1]["f"] = curserch(A,1,0,P,n)
j=1
for i in range(1,n+1):
    print(i,P[i]["d"],P[i]["f"])

Python: def disc(s,d):
	ans[d][0] = s
	s += 1
	if main[d][0] != 0:
		for l in range(1,int(main[d][0])+1):
			if ans[int(main[d][l])-1][0] == 0:
				s = disc(int(s),int(main[d][l])-1)
	ans[d][1] = s
	return s+1

n = int(input())

main = []

for i in range(n):
	a = input().split()
	if int(a[1]) > 0:
		main.append(a[1:])
	else:
		main.append([0])

del a

ans = [[0] * 2 for i in range(n)]

ls = disc(1,0)
for i in range(n):
	if ans[i][0] == 0:
		ls = disc(int(ls),i)


for i in range(n):
	print(str(i+1) + " " + str(ans[i][0]) + " " + str(ans[i][1]))