Go: package main

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

type vertexId int

type vertex struct {
	id vertexId
	firstVisitAt int
	finishVisitAt int
	adjs []vertexId
}

func createVertex(id int, adjsInt []int) vertex {
	adjs := make([]vertexId, len(adjsInt))
	for i := 0; i < len(adjs); i++ {
		adjs[i] = vertexId(adjsInt[i])
	}
	return vertex{
		id: vertexId(id),
		firstVisitAt: 0,
		finishVisitAt: 0,
		adjs: adjs,
	}
}

func (v *vertex) isVisited() bool {
	return v.firstVisitAt > 0
}

func dfs(currentId vertexId, timestamp int, vertices []vertex) int {
	currentVertex := &vertices[currentId-1]
	if currentVertex.isVisited() {
		return timestamp
	}
	timestamp = timestamp + 1
	currentVertex.firstVisitAt = timestamp
	for _, adjId := range currentVertex.adjs {
		timestamp = dfs(adjId, timestamp, vertices)
	}
	timestamp = timestamp + 1
	currentVertex.finishVisitAt = timestamp
	return timestamp
}

func solveDfs(vertices []vertex) {
	timestamp := 0
	for {
		vid := vertexId(-1)
		for i := 0; i < len(vertices); i++ {
			if !vertices[i].isVisited() {
				vid = vertexId(i+1)
				break
			}
		}
		if vid > 0 {
			timestamp = dfs(vid, timestamp, vertices)
		} else {
			break
		}
	}
}

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

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

	vertices := make([]vertex, n)
	for i := 0; i < n; i++ {
		id, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjN, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjs := make([]int, adjN)
		for j := 0; j < adjN; j++ {
			adjId, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			adjs[j] = adjId
		}
		vertices[i] = createVertex(id, adjs)
	}

	solveDfs(vertices)

	for i := 0; i < n; i++ {
		fmt.Printf("%d %d %d\n", vertices[i].id, vertices[i].firstVisitAt, vertices[i].finishVisitAt)
	}
}

func nextText(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

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

Python: def h(G,G1,d,f,c,tmp,tmp1,n):
    if c[0]==2:
        f[0]=f[tmp]+1
        return 0
    cnt=0
    for i in range(n):
        if G1[tmp1][i]==1:
            if c[i]==0:
                d[i]=d[tmp1]+1
                c[i]+=1
                tmp=tmp1
                tmp1=i
                G1[tmp][i]=0
                h(G,G1,d,f,c,tmp,tmp1,n)

        else:
            cnt+=1
            if cnt==n:
                if c[tmp1]==1:
                    d[tmp1]=d[tmp]+1
                    c[tmp1]+=1
                    f[tmp1]=d[tmp1]+1
                    tmp=tmp1
                    for j in range(n):
                        if G[j][tmp]==1:
                            tmp1=j
                    G1[j][tmp1]=0
                    c[tmp1]+=1
                    h(G,G1,d,f,c,tmp,tmp1,n)
                elif c[tmp1]==2:
                    f[tmp1]=f[tmp]+1
                    tmp=tmp1
                    for j in range(n):
                        if G[j][tmp]==1:
                           tmp1=j
                           G1[j][tmp]=0
                    c[tmp1]+=1
                    h(G,G1,d,f,c,tmp,tmp1,n)
n=int(input())
d=[1 for i in range(n)]
f=[0 for i in range(n)]
c=[0 for i in range(n)]
G=[[0 for i in range(n)]for j in range(n)]
G1=[[0 for i in range(n)]for j in range(n)]
u=[0 for i in range(n)]
for i in range(n):
    A=input().split()
    u[i]=int(A[0])
    k=int(A[1])
    for j in range(k):
        x=int(A[j+2])-1
        G[i][x]=1
        G1[i][x]=1

d[0]=1
c[0]+=1
for i in range(n):
    if G[0][i]==1:
        d[i]=d[0]+1
        c[i]+=1
        tmp=0
        tmp1=i
        G1[0][i]=0
        break
h(G,G1,d,f,c,tmp,tmp1,n)
for i in range(n):
    print(i+1,d[i],f[i])

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])