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

	timer := 1
	startNode := 1
	for {
		visit(startNode, &timer, childrenMap, timeRecordMap)
		startNode = findStartNode(childrenMap, timeRecordMap)
		if startNode < 0 {
			break
		}
	}
	for k, v := range timeRecordMap {
		fmt.Printf("%d %d %d\n", k+1, v.discoverTime, v.finishTime)
	}
}

func findStartNode(childrenMap [][]int, timeRecordMap []TimeRecord) int {
	x := -1
	for node, timeRecord := range timeRecordMap {
		if timeRecord.discoverTime < 0 {
			x = node + 1
			break
		}
	}
	return x
}

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: n=int(input())

l=[[0 for i in range(n)] for j in range(n)]##静的確保 隣接行列
d=[0 for i in range(n)]##発見
f=[0 for i in range(n)]##完了
stack=[]##スタック
check=[]

for i in range(n):
    p=[int(x) for x in input().split()]
    
    for j in range(n):
        if j+1 in p[2:]:
            l[i][j]=1
##print("---隣接行列---")
##print(l)

time=1


while len(check)<n:
    for i in range(n):
        if i+1 not in check:
            stack+=[i+1]
            d[i]=time
            break
        else: pass

    while len(stack)!=0:
        print("----------while---------")
        for i in range(n):
            if l[stack[-1]-1][i]==1 and not i+1 in check and stack[-1]-1!=i:
                time+=1
                d[i]=time
                stack+=[i+1]

               ## print("stack:",stack)
               ## print("check:",check)
               ## print("d[",i,"]:",d[i])
                break
            elif i==n-1:
##最深    
                check+=[stack[-1]]
                time+=1
                f[stack.pop()-1]=time

               ## print("f[",i,"]:",f[i])
               ## print("check:",check)
    time+=1


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

Python: n = int(input())

from collections import deque

graph = [deque([]) for _ in range(n+1)]

for _ in range(n):
    u, k, *v = [int(x) for x in input().split()]

    v.sort()
    for i in v:
        graph[u].append(i)
    
arrive = [-1 for i in range(n+1)]
finish = [-1 for i in range(n+1)]

times = 0

def dfs(v):
    global times
    times += 1
    arrive[v] = times
    stack = [v]
    
    while stack:
        v = stack[-1]
        if graph[v]:
            w = graph[v].popleft()
            if arrive[w] == -1:
                times += 1
                arrive[w] = times
                stack.append(w)
        else:
            times += 1
            finish[v] = times
            stack.pop()
    return

for i in range(n):
    if arrive[i+1] == -1:
        dfs(i+1)

for j in range(n):
    tmp = [j+1, arrive[j+1], finish[j+1]]
    print(*tmp)

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

visited=[0 for i in range(n)]
finished=[0 for i in range(n)]
L=[]
out=[[i+1,0,0] for i in range(n)]
step=0

def dfs(cn):
    flg=0
    if visited[cn]==0:
        flg=1
        L.append(cn)
    visited[cn]=1
    for i in range(n):
        if cn!=i and G[cn][i]==1 and visited[i]==0:
            dfs(i)
    if flg==1:
        L.append(cn)

i=0
while visited.count(1)<n:
    dfs(i)
    i+=1
copied=[0 for i in range(len(L))]

for i in range(len(L)):
    if copied[L[i]]==0:
        copied[L[i]]=1
        out[L[i]][1]=i+1
    elif copied[L[i]]==1:
        copied[L[i]]=2
        out[L[i]][2]=i+1

out=[' '.join(map(str,i)) for i in out]
#print(' '.join(map(str,[i+1 for i in L])))
print('\n'.join(map(str,out)))

Python: import sys
u=[]
k=[]
v=[]

time = 0

n=int(sys.stdin.readline().strip())
yattayatu=[False for i in range(n)]

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

for i in range(n):
	inp = sys.stdin.readline().strip().split(" ")
	inp = list(map(lambda x: int(x), inp))
	u.append(inp[0])
	k.append(inp[1])
	v.append(inp[2:])


def func(nodeid):
	global time
	if(yattayatu[nodeid-1]==True):
		return
	time += 1
	s[nodeid-1] = time
	for i in range(k[nodeid-1]):
		func(v[nodeid-1][i])
	time +=1
	f[nodeid-1]=time
	yattayatu[nodeid-1]=True

func(1)

for i in range(n):
	print(str(i+1)+" "+str(s[i])+" "+str(f[i]))

Python: def dfs(G, u, t, d, visited):
  found = t
  visited.add(u)
  t += 1
  for v in G[u]:
    if v not in visited:
      t = dfs(G, v, t, d, visited)
  complete = t
  d[u] = (found, complete)
  t+=1
  return t


n = int(input())
G = {}
for _ in range(n):
  entries = list(map(int, input().split(' ')))
  u = entries[0]
  k = entries[1]
  G[u] = set()
  for v in entries[2:]:
    G[u].add(v)


d = {}
dfs(G, 1, 1, d, set())
for i in sorted(d):
  print(i,d[i][0],d[i][1])

Python: n = int(input())
a = []
for i in range(n):
    a += [list(map(int, input().split()))[2:]]
cnt = 1
pre = [0]*n
aft = [0]*n
color = [0]*n
def dfs(s):
    global cnt
    pre[s-1] = cnt
    cnt += 1
    color[s-1] = 1
    for i in a[s-1]:
        if color[i-1] == 0:dfs(i)
    aft[s-1] = cnt
    cnt += 1

for i in range(n):
    if color[i] == 0:
        dfs(i+1)

for i in range(n):
    print(i+1, pre[i], aft[i])

Python: #coding: utf-8

n = int(input())
color = ["white" for i in range(n)]
d = [[] for i in range(n)]
global t
t = 0
M = [[False for i in range(n)] for j in range(n)]
for i in range(n):
    data = list(map(int,input().split()))
    u = data[0]
    k = data[1]
    if i == 0:
        start = u
    for v in data[2:2+k]:
        M[u-1][v-1] = True


def search(u,t):
    t += 1
    color[u-1] = "gray"
    d[u-1].append(t)
    for v in range(1,n+1):
        if M[u-1][v-1] and color[v-1] == "white":
            t = search(v,t)
    color[u-1] = "black"
    t += 1
    d[u-1].append(t)
    return t

t = search(start, t)
for i in range(1,n+1):
    if color[i-1] == "white":
        t = search(i, t)

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

Python: def DPS(graph,vertex,dis_time,fin_time,tmp_time):
    dis_time[vertex]=tmp_time[0]
    for i in range(len(graph[0])):
        if(graph[vertex][i] !=0 and dis_time[i]==0):#枝先の頂点が探索済みでなかったら、
            tmp_time[0]+=1
            DPS(graph,i,dis_time,fin_time,tmp_time)
    
    if(dis_time[vertex]==tmp_time[0]):#vertexから、どの頂点に対しても調査が進まなかったら
        tmp_time[0]+=1
    fin_time[vertex]=tmp_time[0]
    tmp_time[0]+=1



#グラフの作成
n=int(input())
graph=[[0]*n for loop in range(n)]
for loop in range(n):
    tmp_ope=list(map(int,input().split()))
    for j in range(tmp_ope[1]):
        graph[tmp_ope[0]-1][tmp_ope[j+2]-1]=1


dis_time=[0]*n
fin_time=[0]*n
tmp_time=[1]
for i in range(n):
    if(dis_time[i]==0):
        DPS(graph,i,dis_time,fin_time,tmp_time)

for i in range(n):
    print(f"{i+1} {dis_time[i]} {fin_time[i]}")