Go: package main

import (
	"fmt"
)

func main() {
	var n int
	fmt.Scan(&n)
	g := make([][]int, n+1)
	for i := 0; i < n; i++ {
		var u,k int
		fmt.Scan(&u)
		fmt.Scan(&k)
		g[u] = make([]int, k)
		for j := 0; j < k; j++ {
			fmt.Scan(&g[u][j])
		}
	}

	d := make([]int, n+1)
	f := make([]int, n+1)
	t := 1
	for i := 1; i <= n; i++ {
		t = dfs(&g, &d, &f, i, t)
	}

	for i := 1; i <= n; i++ {
		fmt.Printf("%d %d %d\n", i, d[i], f[i])
	}
}

func dfs(g *[][]int, d *[]int, f *[]int, id int, t int) int {
	if (*d)[id] > 0 {
		return t
	}
	(*d)[id] = t
	t += 1
	for i := 0; i < len((*g)[id]); i++ {
		t = dfs(g, d, f, (*g)[id][i], t)
	}
	(*f)[id] = t
	return t+1
}

Python: class Node:

    def __init__(self):
        self.distime = 0
        self.fintime = 0

    def input_data(self, nodes):
        data = input().split()
        self.number = int(data[0])
        self.v = [nodes[int(x) - 1] for x in data[2:]]

    @property
    def status(self):
        return bool(self.distime) + bool(self.fintime)

class Stack:
    def __init__(self, size):
        self.size = size
        self.N = [None for _ in range(size)]
        self.top = 0

    def is_emtpy(self):
        return self.top == 0

    def is_full(self):
        return self.top == self.size

    def front(self):
        return self.N[self.top - 1]

    def push(self, x):
        if self.is_full():
            raise OverflowError
        self.N[self.top] = x
        self.top += 1

    def pop(self):
        if self.is_emtpy():
            raise IndexError
        self.top -= 1
        return self.N[self.top]


def visit(node: Node):
    global t
    stack.push(node)
    t += 1
    node.distime = t
    while not stack.is_emtpy():
        u: Node = stack.front()
        try:
            v = next(i for i in u.v if i.status == 0)
        except StopIteration:
            stack.pop()
            t += 1
            u.fintime = t
        else:
            if v.status == 0:
                stack.push(v)
                t += 1
                v.distime = t


n = int(input())
stack = Stack(n)
nodes = [Node() for _ in range(n)]
[node.input_data(nodes) for node in nodes]
t = 0
for node in nodes:
    if node.status == 0:
        visit(node)

nodes.sort(key=lambda i: i.number)
for node in nodes:
    print(f"{node.number} {node.distime} {node.fintime}")

Python: # https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/11/ALDS1_11_B
# 本の解説通りかは知らない

# データの読み込み
N = int(input())
DG = {}
node_ls = []
is_visited = {}
# 有向グラフをディクトで管理することにする
for _ in range(N):
    tmp = input().split()
    node_id = tmp[0]
    node_ls.append(node_id)
    is_visited[node_id] = False
    adj_num = int(tmp[1])
    if adj_num != 0:
        DG[node_id] = tmp[2:]
    else:
        DG[node_id] = []

d = {}  # 最初に訪問したときの発見時刻を記録する
f = {}  # 隣接リストを調べ終えた完了時刻を記録する
t = 1


def dfs(node):  # 必要なものは何？ 現在のノード
    # 終了条件
    global t
    if is_visited[node]:
        return  # 何もせずに上の関数に抜ける

    is_visited[node] = True
    # 発見時刻の書き込み
    d[node] = t
    t += 1  # 時刻を一つ進める
    # 再帰探索
    for no in DG[node]:
        dfs(no)
    f[node] = t
    t += 1  # 関数を終了するときにも+1する


for node in node_ls:  # 孤立しているノードもあるためこうして対処
    dfs(node)

for node in node_ls:
    print(node, d[node], f[node])

Python: N = int(input())
L = [[] for i in range(N+1)]
d = [0] * (N+1)
f = [0] * (N+1)

time = 0

def dfs(key):
    global time
    time += 1
    d[key] = time
    for i in range(len(L[key])):
        if d[L[key][i]] == 0:
            dfs(L[key][i])
    time += 1
    f[key] = time
        

for i in range(N):
    Q = list(map(int, input().split()))
    L[Q[0]].extend(Q[2:])

for i in range(1,N+1):
    if d[i] == 0:
        dfs(i)
        #print("done")

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

Python: n = int(input())
graph = [[0 for i in range(n)] for j in range(n)]
d = [0] * n
f = [0] * n
g = [0] * n

time = 0

for i in range(n):
   a = list(map(int, input().split()))
   for j in range(0, a[1], 1):
       graph[a[0] - 1][a[2 + j] - 1] = 1

def search(i):
    global time
    time = time + 1
    d[i] = time
    g[i] = 1
    for j in range(n):
        if (graph[i][j] == 1) & (g[j] == 0):
            search(j)
    time = time + 1
    f[i] = time

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

Python: import sys


def input():
    return sys.stdin.readline().rstrip()


def dfs(c, n, G, ans):
    count = c
    for i, flag in enumerate(G[n]):
        if flag == 1 and ans[i][0] == 0:
            count += 1
            ans[i][0] = i + 1
            ans[i][1] = count
            ans[i][2] = dfs(count, i, G, ans)
            count = ans[i][2]
    else:
        return count + 1


def main():
    n = int(input())
    G = [[0] * n for _ in range(n)]
    ans = [[0] * 3 for _ in range(n)]
    for i in range(n):
        u, k, *v = map(int, input().split())
        for j in range(k):
            G[u-1][v[j]-1] = 1

    count = 1
    for i in range(n):
        if ans[i][0] == 0:
            ans[i][0] = i + 1
            ans[i][1] = count
            ans[i][2] = dfs(count, i, G, ans)
            count = ans[i][2] + 1

    for i in range(n):
        print(*ans[i])


if __name__ == '__main__':
    main()

Python: from collections import deque

n = int(input())

g = [deque([]) *n for _ in range(n)]

for i in range(n):
    u, k, *V = list(map(int, input().split()))
    V.sort()
    for v in V:
        g[u-1].append(v-1)
        # g[v-1].append(u-1)

time = 0
arrive_time = [-1] * n
finish_time = [-1] * n
def dfs(v):
    global time
    time += 1
    stack = [v]
    arrive_time[v] = time
    while stack:
        v = stack[-1]
        if g[v]:
            w = g[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] < 0:
        ans = dfs(i)

for j in range(n):
    temp = [j+1, ans[0][j], ans[1][j]]
    print(*temp)

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