Go: package main

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

type TimeRecord struct {
	discoverTime int
	finishTime   int
}

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

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

	timeRecordMap := make([]TimeRecord, n)
	childrenMap := make([][]int, n)
	for i := 1; i <= n; i++ {
		node, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		timeRecordMap[node-1] = TimeRecord{-1, -1}

		childNum, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		childrenMap[node-1] = make([]int, childNum)
		for j := 0; j < childNum; j++ {
			child, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			childrenMap[node-1][j] = child
		}
	}

	// TODO: always start with 1?
	timer := 1
	visit(1, &timer, childrenMap, timeRecordMap)
	for k, v := range timeRecordMap {
		fmt.Printf("%d %d %d\n", k+1, v.discoverTime, v.finishTime)
	}
}

func visit(currentNode int, timer *int, childrenMap [][]int, timeRecordMap []TimeRecord) {
	if timeRecordMap[currentNode-1].discoverTime > 0 {
		return
	}
	children := childrenMap[currentNode-1]
	timeRecordMap[currentNode-1] = TimeRecord{*timer, timeRecordMap[currentNode-1].finishTime}
	(*timer)++
	for i := 0; i < len(children); i++ {
		visit(children[i], timer, childrenMap, timeRecordMap)
	}
	timeRecordMap[currentNode-1] = TimeRecord{timeRecordMap[currentNode-1].discoverTime, *timer}
	(*timer)++
}

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

Python: time=1
n=int(input())

A=[[] for i in range(n)]
d=[0 for i in range(n)]
f=[0 for i in range(n)]

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

def dfs(q,num):
	global d,f,time
	d[num]=time
	for nx in q[num]:
		if d[nx]==0:
			time+=1
			dfs(q,nx)
	time+=1
	f[num]=time
	
for i in range(n):
	if d[i]==0:#unvisit
		dfs(A,i)

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

Python: N = 100
WHITE = 0
GRAY = 1
BLACK = 2

d = [-1] * N
f = [-1] * N

def dfs_visit(n, u, tt, color):
    global d
    global f
    color[u] = GRAY
    tt += 1
    d[u] = tt
    for v in range(n):
        if M[u][v] == 0:
            continue
        if color[v] == WHITE:
            tt = dfs_visit(n, v, tt, color)
    color[u] = BLACK
    tt += 1
    f[u] = tt
    return tt

def dfs(n):
    global d
    global f
    color = []
    for u in range(n):
        color.append(WHITE)
    tt = 0

    for u in range(n):
        if color[u] == WHITE:
            tt = dfs_visit(n, u, tt, color)
    
    for u in range(n):
        print(u+1, d[u], f[u])

n = int(input())

M = [[0] * n for _ in range(n)]

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

#print(M)

dfs(n)

Python: n = int(input())

m = [[0 for i in range(n)] for j in range(n)]

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

color = ["white" for i in range(n)]

d = [0 for i in range(n)]
f = [0 for i in range(n)]
time = 0

def dfs(u):
    global time
    time += 1
    color[u] = "gray"
    d[u] = time
    for i in range(u, n):
        if m[u][i] and color[i] == "white":
            dfs(i)
    color[u] = "black"
    time += 1
    f[u] = time

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

Python: import sys
sys.setrecursionlimit(2000000)

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

def dfs(x, time):
    first[x] = time
    time += 1
    for v in m[x]:
        if first[v-1] == 0:
            time = dfs(v-1, time)
    finish[x] = time
    time += 1
    return time

first = [0] * n
finish = [0] * n

time = 1
for i in range(n):
    if first[i] == 0:
        time = dfs(i, time)

for i, xy in enumerate(zip(first, finish)):
    print(i+1, *xy)

Python: #16D8101014F KurumeRyunosuke 2018/6/20

n=int(input())
ls=[[0 for i in range(n)]for j in range(n)]
for i in range(n):
	tmp=input().split()
	for j in range(int(tmp[1])):
		ls[i][int(tmp[j+2])-1]=1

"""
for i in range(n):
    for j in range(n):
        if(j!=n-1):
            print(int(ls[i][j]), end=' ')
        else:
            print(int(ls[i][j]))
"""
stuck=[0]
count=1
d=[0 for i in range(n)]
f=[0 for i in range(n)]
d[0]=count
while True:
	count+=1
	p=0
	for i in range(n):
		if ls[stuck[len(stuck)-1]][i] is not 0:
			ls[stuck[len(stuck)-1]][i]=0
			
			p=1
			#print(stuck)
			stuck.append(i)
			d[stuck[len(stuck)-1]]=count
			break

	if p is 1:
		for i in range(n):
			ls[i][stuck[len(stuck)-1]]=0
	if p is 0:
		#print("//")
		a=stuck.pop()
		f[a]=count
		for i in range(n):
			ls[a][i]=0

	if len(stuck) is 0:
		t=0
		for i in range(n):
			for j in range(n):
				if ls[i][j] is not 0 and t is 0:
					count+=1
					stuck.append(i)
					d[stuck[len(stuck)-1]]=count
					#print(i)
					t=1
					
		if t is 0:
			break
		#print("break")

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

Python: import sys
import itertools
# import numpy as np
import time
import math
 
sys.setrecursionlimit(10 ** 7)
 
from collections import defaultdict
 
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines

N = int(input())

adj = [[] for _ in range(N)]

for i in range(N):
    line = list(map(int, input().split()))
    u = line[0] - 1
    if line[1] == 0:
        continue
    vs = line[2:]
    for v in vs:
        adj[u].append(v - 1)

d = [-1] * N
f = [-1] * N

def dfs(v, t):
    d[v] = t
    nx = t + 1
    for u in adj[v]:
        if d[u] > -1:
            continue
        nx = dfs(u, nx)
    f[v] = nx
    return f[v] + 1

nx = 1
for i in range(N):
    if d[i] > - 1:
        continue
    nx = dfs(i, nx)

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

Python: #!/usr/bin/env python
from __future__ import division, print_function
from sys import stdin


def walk(index, tm, L, d, f):
    tm += 1
    d[index] = tm
    for i in L[index]:
        if not d[i-1]:
            tm = walk(i-1, tm, L, d, f)
    tm += 1
    f[index] = tm
    return tm


def main():
    num = int(stdin.readline())

    L = []
    for _ in xrange(num):
        L.append([int(s) for s in stdin.readline().split()[2:]])

    d = [0] * num
    f = [0] * num
    tm = 0
    for i in xrange(num):
        if not d[i]:
            tm = walk(i, tm, L, d, f)

    for i in xrange(num):
        print(i+1, d[i], f[i])


main()

Python: n = int(input())
G = [[] for _ in range(n)]
u1 = 0
for _ in range(n):
    u, k, *v = [int(i) for i in input().split()]
    G[u - 1] = v
    if k != 0 and u1 == 0:
        u1 = u

time = 1
u = u1
D = []
F = []
out = [[i+1, 0, 0] for i in range(n)]
T = []
while True:
    if u not in D:
        out[u - 1][1] = time
        D.append(u)
        T.append(u)

    for f in F:
        if f in G[u - 1]:
            idx = G[u - 1].index(f)
            del G[u - 1][idx]

    if G[u - 1] == []:
        time += 1
        out[T.pop() - 1][2] = time
        F.append(u)
        if T == []:
            if len(D) == n:
                break
            else:
                for ni in range(n):
                    if ni + 1 not in D:
                        u = ni + 1
                        break
                time += 1
                continue
        else:
            u = T[-1]
    else:
        if G[u - 1][0] not in D:
            time += 1
        u = G[u - 1].pop(0)

for ni in range(n):
    print(*out[ni])