Go: package main

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

func getScanner(fp *os.File) *bufio.Scanner {
	scanner := bufio.NewScanner(fp)
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 1000005), 1000005)
	return scanner
}

func getNextString(scanner *bufio.Scanner) string {
	scanner.Scan()
	return scanner.Text()
}

func getNextInt(scanner *bufio.Scanner) int {
	i, _ := strconv.Atoi(getNextString(scanner))
	return i
}

func getNextInt64(scanner *bufio.Scanner) int64 {
	i, _ := strconv.ParseInt(getNextString(scanner), 10, 64)
	return i
}

func getNextUint64(scanner *bufio.Scanner) uint64 {
	i, _ := strconv.ParseUint(getNextString(scanner), 10, 64)
	return i
}

func getNextFloat64(scanner *bufio.Scanner) float64 {
	i, _ := strconv.ParseFloat(getNextString(scanner), 64)
	return i
}

func main() {
	fp := os.Stdin
	wfp := os.Stdout
	cnt := 0

	if os.Getenv("MASPY") == "ますピ" {
		fp, _ = os.Open(os.Getenv("BEET_THE_HARMONY_OF_PERFECT"))
		cnt = 1
	}
	if os.Getenv("MASPYPY") == "ますピッピ" {
		wfp, _ = os.Create(os.Getenv("NGTKANA_IS_GENIUS10"))
	}

	scanner := getScanner(fp)
	writer := bufio.NewWriter(wfp)
	solve(scanner, writer)
	for i := 0; i < cnt; i++ {
		fmt.Fprintln(writer, "-----------------------------------")
		solve(scanner, writer)
	}
	writer.Flush()
}

func solve(scanner *bufio.Scanner, writer *bufio.Writer) {
	n := getNextInt(scanner)
	g := graph{}
	g.ee = make([]Edges, n)
	g.visited = make([]bool, n)
	g.found = make([]int, n)
	g.leave = make([]int, n)
	for i := 0; i < n; i++ {
		u := getNextInt(scanner) - 1
		k := getNextInt(scanner)
		for j := 0; j < k; j++ {
			v := getNextInt(scanner) - 1
			g.ee[u] = append(g.ee[u], Edge{
				to: v,
				id: u,
			})
		}
	}
	for i := 0; i < n; i++ {
		sort.Sort(g.ee[i])
	}
	for i := 0; i < n; i++ {
		if g.visited[i] {
			continue
		}
		g.dfs(i)
	}

	for i := 0; i < n; i++ {
		fmt.Fprintln(writer, fmt.Sprintf("%d %d %d", i+1, g.found[i], g.leave[i]))
	}
}

// Edge ...
type Edge struct {
	to, id int
}

type Edges []Edge

func (a Edges) Len() int           { return len(a) }
func (a Edges) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a Edges) Less(i, j int) bool { return a[i].id < a[j].id }

type graph struct {
	ee           []Edges
	t            int
	n            int
	visited      []bool
	found, leave []int
}

func (g *graph) dfs(i int) {
	g.visited[i] = true
	g.t++
	g.found[i] = g.t
	for _, e := range g.ee[i] {
		if g.visited[e.to] {
			continue
		}
		g.dfs(e.to)
	}
	g.t++
	g.leave[i] = g.t
}

Python: n=int(input())
g=[]
for i in range(n):
    u,k,*varray= map(int,input().split())
    g.append(varray)

time = 1
d= [-1]* n
f= [-1]* n

def dfs(src):
    global time
    d[src]= time
    time+=1
    for i in g[src]:
        if d[i-1]== -1:
            dfs(i-1)
    f[src]= time
    time+=1

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

Python: N = int(input())
adj_list = [ [] for _ in range(N+1) ]
for _ in range(N):
  lst = list(map(int,input().split()))
  node = lst[0]
  if lst[1] != 0:
    adj_list[node] = lst[2:]


visited = [False] * (N+1)
arrived = [-1] * (N+1)
left = [-1] * (N+1)

time = 0
def dfs(node):
  global time

  arrived[node] = time
  visited[node] = True

  for nei in adj_list[node]:
    if not visited[nei]:
      time += 1
      dfs(nei)
  else:
    time += 1
    left[node] = time

for i in range(1, N+1):
  if not visited[i]:
    time += 1
    dfs(i)

for i in range(1, N+1):
  print(i, arrived[i], left[i])

Python: # coding: utf-8
def depth(i, adj, Dep, Arr, times):
    if Dep[i-1]:
        return times
    Dep[i-1]=times
    times+=1
    # t=[depth(j, adj, Dep, f, times) j in adj[i-1]]
    for j in adj[i-1]:
        times=depth(j, adj, Dep, Arr, times)
    Arr[i - 1]=times
    times+=1
    return times


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

d,f=[0]*n,[0]*n

t=1

dlist=[i for i in range(n) if d[i]==0]

for i in dlist:
    t = depth(i + 1, adj, d, f, t)

for i, df in enumerate(zip(d, f)):
    print(i + 1, *df)

Python: def main():

    inf = 1000000007
    n = int(input())
    e = [[] for _ in range(n)]
    d = [inf]*n
    f = [inf]*n
    step = 1

    def dfs(v):
        nonlocal step
        d[v] = step
        step+=1
        for u in e[v]:
            if d[u] == inf:dfs(u)
        f[v] = step
        step +=1

    e = [[] for _ in range(n)]
    for i in range(n):
        m = list(map(int,input().split()))
        for j in range(2,len(m)):
            e[m[0]-1].append(m[j]-1)
    for i in range(n):
        if d[i]==inf:dfs(i)
    for i in range(n):
        print (i+1,d[i],f[i])

if __name__ == '__main__':
    main()

Python: import collections,sys
def I(): return int(sys.stdin.readline().rstrip())
def LI(): return list(map(int,sys.stdin.readline().rstrip().split()))
n = I()
ukv = [LI() for _ in range(n)]
graph = {i:collections.deque() for i in range(1,n+1)} #1_indexed
for x in ukv:
    u,k,*v = x
    for y in v:
        graph[u].append(y)
seen = [0]*(n+1) #1_indexed
stack = []
time = 0
seentime = [0]*(n+1) #1_indexed
donetime = [0]*(n+1) #1_indexed
def dfs(j):
    global time
    seen[j] = 1
    stack.append(j)
    time += 1
    seentime[j] = time
    while stack:
        s = stack[-1]
        if not graph[s]:
            stack.pop()
            time += 1
            donetime[s] = time
            continue
        g_NO = graph[s].popleft()
        if seen[g_NO]:
            continue
        seen[g_NO] = 1
        stack.append(g_NO)
        time += 1
        seentime[g_NO] = time
for j in range(1,n+1):
    if seen[j]:
        continue
    dfs(j)
for k,a,b in zip(range(1,n+1),seentime[1:],donetime[1:]):
    print(k,a,b)

Python: 
#graphの頂点vertex(インデックス、0オリジン)を深さ優先探索。dis_time:最初に訪れた時のtimeを管理するリスト
#fin_time:その頂点に対して、探索が終わった時のtimeを管理するリスト　tmp_time:現在のtime(関数内で変更できるようにリスト)
def DPS(graph,vertex,dis_time,fin_time,tmp_time):
    tmp_time[0]+=1
    dis_time[vertex]=tmp_time[0]
    for i in range(len(graph[0])):
        if(graph[vertex][i] !=0 and dis_time[i]==0):#枝先の頂点が探索済みでなかったら、
            DPS(graph,i,dis_time,fin_time,tmp_time)
    
    tmp_time[0]+=1
    fin_time[vertex]=tmp_time[0]



#グラフの作成
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=[0]
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]}")

Python: def main():
    num = int(input())
    Dst = [None for i in range(num + 1)]
    Fst = [0] * (num + 1)
    Lst = Fst[:]
    S = []

    for n in range(1, num+1):
        a = list(map(int,input().split()))
        u = a[0]
        if a[1] > 0:
            Dst[u] = a[2:]
            Dst[u].reverse()

    cnt = 1
    S.append(1)
    Fst[1] = 1
    while(len(S) > 0):
        cnt += 1
        u = S.pop()
        if Dst[u] is not None and len(Dst[u]) > 0:
            u1 = Dst[u].pop()
            if Fst[u1] == 0:
                S.append(u)
                S.append(u1)
                Fst[u1] = cnt
            else:
                Lst[u] = cnt
        else:
            Lst[u] = cnt

    for n in range(1, num+1):
        print("{} {} {}".format(n,Fst[n],Lst[n]))

if __name__ == '__main__':
    main()