Go: package main

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

func main() {
	scn := bufio.NewScanner(os.Stdin)
	scn.Split(bufio.ScanWords)
	nextInt := func() int { scn.Scan(); r, _ := strconv.Atoi(scn.Text()); return r }
	w := bufio.NewWriter(os.Stdout)

	n := nextInt()
	vecs := make([][]int, n)
	for i := 0; i < n; i++ {
		u := nextInt()
		k := nextInt()
		for j := 0; j < k; j++ {
			vecs[u-1] = append(vecs[u-1], nextInt()-1)
		}
	}

	ds := make([]int, n)
	fs := make([]int, n)
	founds := make([]bool, n)
	t := 0
	for i := range founds {
		if !founds[i] {
			t = dfs(vecs, ds, fs, founds, i, t)
		}
	}

	for i := 0; i < n; i++ {
		fmt.Fprintln(w, i+1, ds[i], fs[i])
	}

	w.Flush()
}

func dfs(vecs [][]int, ds, fs []int, founds []bool, i, t int) (time int) {
	t++
	ds[i] = t
	founds[i] = true
	for _, v := range vecs[i] {
		if !founds[v] {
			t = dfs(vecs, ds, fs, founds, v, t)
		}
	}
	t++
	fs[i] = t

	return t
}

Python: # coding: utf-8
import itertools
import math
import bisect

class Node:
    def __init__(self, id, next, rest):
        self.id = id
        self.before = None
        self.next = next
        self.rest = rest
        self.d = None
        self.f = None

    def update_next(self):
        self.next = first(self.rest)
        self.rest = rest(self.rest)


N = int(input())
graph = []
for _ in range(N):
    l = list(map(int, input().split(" ")))
    id = l[0]
    if l[1] != 0:
        next = l[2]
    else:
        next = None
    if l[1] >= 2:
        rest = l[3:]
    else:
        rest = []
    graph.append(Node(l[0], next, rest))

def first(l):
    if l==None:
        return None
    if len(l) == 0:
        return None
    else:
        return l[0]

def rest(l):
    if l == None:
        return None
    if len(l) >= 2:
        return l[1:]
    else:
        return None

def dfs(graph):
    stack = [graph[0]]
    stack[-1].d = 1
    tansakuzumi = [1]
    mitansaku = list(range(1, len(graph)+1))
    res_graph = []
    t = 2
    while len(stack) != 0:
        tansakuzumi.append(stack[-1].id)
        if stack[-1].id in mitansaku:
            mitansaku.remove(stack[-1].id)
        if stack[-1].next == None:
            stack[-1].f = t
            res_graph.append(stack.pop())
            t += 1
        elif stack[-1].next in tansakuzumi:
            stack[-1].update_next()
        else:
            stack.append(graph[stack[-1].next-1])
            stack[-2].update_next()
            stack[-1].d = t
            t += 1
        if len(stack) == 0 and len(mitansaku) >= 1:
            stack.append(graph[mitansaku[0]-1])
            stack[-1].d = t
            t += 1
    return res_graph




res_graph = dfs(graph)

res_graph.sort(key=lambda x: x.id)

for n in res_graph:
    print("{} {} {}".format(n.id, n.d, n.f))

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
_ = dfs(0, 1)
for i, (d, f) in enumerate(zip(D, F)):
    print(i, d, f)

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

d = [0] * n
f = [0] * n
isDiscovered = [False] * n
time_stamp = 0

def dfs(x):
    global time_stamp
    isDiscovered [x] = True
    time_stamp = time_stamp + 1
    d[x] = time_stamp
    for i in range(n):
        if a[x][i] == 1 and isDiscovered[i] == False:
            dfs(i)
    time_stamp = time_stamp + 1
    f[x] = time_stamp

for i in range(n):
    if isDiscovered[i] == False:
        dfs(i)

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

Python: from sys import stdin
input = stdin.readline

N = int(input())
WHITE = 0
GRAY = 1
BLACK = 2

M = [[0]*N for _ in range(N)]
color = [WHITE]*N  # colorの初期化は最初に行っておく。
d = [0]*N
f = [0]*N

def dfs_visit(u):
    global tt
    color[u] = GRAY
    tt += 1
    d[u] = tt # 最初の訪問
    for v in range(N):
        if M[u][v] == 0:
            continue
        if color[v] == WHITE:
            dfs_visit(v)
    color[u] = BLACK
    tt += 1
    f[u] = tt # 訪問の完了

def dfs():
    global tt
    tt = 0

    for u in range(N):
        if color[u] == WHITE:
            # 未訪問のuを始点として深さ優先探索
            dfs_visit(u)
    for u in range(N):
        print(str(u+1) + ' ' + str(d[u]) + ' ' + str(f[u]))
for _ in range(N):
    u, k, *vv = input().split()
    u = int(u)-1  # 0オリジンにする
    k = int(k)    # kは使わない
    for v in vv:
        v = int(v)-1
        M[u][v] = 1
dfs()

Python: global t
t = 0

class Node:
    def __init__(self, num, deg, neib):
        self.num = num
        self.deg = deg
        self.neib = neib

def dfs(G, d, f, now): #now:1,2,...
    #print("now:",now)
    global t
    t += 1
    #print("t:",t)
    if d[now-1] != 0:
        t -= 1
        #print("has searched or hit roop")
    else:
        d[now-1] = t
        #print("d:",d)
        #print("f:",f)
        for i in G[now-1].neib:
            #print("i:",i)
            if i != -1:
                #print("next node")
                dfs(G, d, f, i)
            #else: print("end of branch")
        t += 1
        f[now-1] = t

        #print("f:",f)


dnum = int(input()) #頂点数
N = []
for i in range(dnum):
    data = input().split()
    
    u = int(data[0])
    k = int(data[1])
    if k > 0:
        v = list(map(int, data[2:]))
    else:
        v = [-1]

    node = Node(u,k,v)
    N.append(node)

d = [0]*dnum #find time
f = [0]*dnum #finish time

while 0 in d:
    s = d.index(0)
    dfs(N, d, f, s+1)
    #print("looks like finish")

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

Python: class Node(object):
    def __init__(self, V):
        self.V = V
        self.find_time = 0
        self.finish_time = 0
        self.is_finded = False


n = int(input())
nodes = [0] * 100
for i in range(n):
    data = input().split()
    V = list(map(int, data[2:]))
    V.sort(reverse = True)
    nodes[int(data[0])] = Node(V)

find_q = []
find_q.append(1)
cnt = 1
q_size = len(find_q)
while q_size != 0:
    #print(find_q)
    node = nodes[find_q[q_size -1]]

    if node.is_finded == False:
        node.find_time = cnt
        cnt += 1
        node.is_finded = True
        if len(node.V) == 0:
            node.finish_time = cnt
            cnt += 1
            del find_q[q_size -1]
            q_size = len(find_q)
        else:
            for x in node.V:
                if x in find_q:
                    find_q.remove(x)
                if nodes[x].finish_time == 0: 
                    find_q.append(x)
            q_size = len(find_q)

    else:   #node is finded
        node.finish_time = cnt
        cnt += 1
        del find_q[q_size -1]
        q_size = len(find_q)
        continue

for i in range(1, n+1):
    print(i, nodes[i].find_time, nodes[i].finish_time)

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