Go: package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

const N = 100

const (
	WHITE = iota
	GRAY
	BLACK
)

type Graph struct {
	M               [N][N]int
	color, d, f, nt [N]int
	tt              int
}

func (g *Graph) next(u, n int) int {
	for v := g.nt[u]; v < n; v++ {
		g.nt[u] = v + 1
		if g.M[u][v] != 0 {
			return v
		}
	}
	return -1
}

func (g *Graph) dfsVisit(r, n int) {
	var S []int
	S = append([]int{r}, S...)
	g.color[r] = GRAY
	g.tt++
	g.d[r] = g.tt

	for len(S) != 0 {
		u := S[0]
		v := g.next(u, n)
		if v == -1 {
			S = S[1:]
			g.color[u] = BLACK
			g.tt++
			g.f[u] = g.tt
			continue
		}

		if g.color[v] != WHITE {
			continue
		}

		g.color[v] = GRAY
		g.tt++
		g.d[v] = g.tt
		S = append([]int{v}, S...)
	}
}

func (g *Graph) dfs(n int) string {
	for i := 0; i < n; i++ {
		g.color[i] = WHITE
	}
	g.tt = 0

	for u := 0; u < n; u++ {
		if g.color[u] == WHITE {
			g.dfsVisit(u, n)
		}
	}

	var out bytes.Buffer
	for i := 0; i < n; i++ {
		out.WriteString(fmt.Sprintf("%d %d %d\n", i+1, g.d[i], g.f[i]))
	}

	return strings.TrimRight(out.String(), "\n")
}

func answer(reader io.Reader) string {
	sc := bufio.NewScanner(reader)
	sc.Split(bufio.ScanWords)

	sc.Scan()
	n, _ := strconv.Atoi(sc.Text())

	var g Graph
	for i := 0; i < n; i++ {
		sc.Scan()
		u, _ := strconv.Atoi(sc.Text())
		sc.Scan()
		k, _ := strconv.Atoi(sc.Text())
		u--
		for j := 0; j < k; j++ {
			sc.Scan()
			v, _ := strconv.Atoi(sc.Text())
			v--
			g.M[u][v] = 1
		}
	}

	return g.dfs(n)
}

func main() {
	fmt.Println(answer(os.Stdin))
}

Python: # -*- coding: utf-8 -*-

def DFS(adj, start):
    n = len(adj)
    d = [0] * n
    f = [0] * n
    flag = [0] * n
    S = []
    time = 1

    S.append(start)
    flag[start] = 1
    d[start] = time
    time = time + 1
    
    while flag.count(2) != n: # ??¨????????????????????¢?´¢????????????????????§
        if len(S) != 0:
            u = S.pop()
            v = next(adj, u)
            v = [i for i in v if flag[i] == 0] # v <= ??£??\???????????????????????¢?´¢??????????????????
            if len(v) != 0:
                S.append(u)
                S.append(v[0])
                flag[v[0]] = 1
                d[v[0]] = time
                time = time + 1
            else:
            #??£??\??????????????¨????¨??????????
                flag[u] = 2
                f[u] = time
                time = time + 1

        else:
            u = flag.index(0)
            S.append(u)
            flag[u] = 1
            d[u] = time
            time = time + 1            

    return d, f



def next(adj, u):
    """
    u?????£??\??????????????????????????????????????????
    """
    return [i for i, x in enumerate(adj[u]) if x == 1]
    

def main():
    
    n = int(input())
    adj = [[0 for i in range(n)] for j in range(n)]

    for i in range(n):
        tmp = list(map(int, input().split()))
        u = tmp[0]
        u = u -1
        k = tmp[1]
        v = tmp[2:]
        for j in range(k):
            adj[u][v[j]-1] = 1
    
    d, f = DFS(adj, 0)
    for i in range(n):
        print(i+1, d[i], f[i])

if __name__ == "__main__":
    main()

Python: def dfs(adj, s, d, f, now):
    now += 1
    d[s] = now
    for t in adj[s]:
        if t != s and f[t] < 0 and d[t] < 0:
            d, f, now = dfs(adj, t, d, f, now)
    now += 1
    f[s] = now
    return d, f, now


n = int(input())
adj = [[] for _ in range(n)]
for _ in range(n):
    s = [int(x) for x in input().split()]
    u = s[0]
    for v in s[2:]:
        adj[u - 1].append(v - 1)
    adj[u - 1].sort()

d = [-1 for _ in range(n)]
f = [-1 for _ in range(n)]
now = 0
for s in range(n):
    if f[s] < 0:
        d, f, now = dfs(adj, s, d, f, now)

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

Python: n = int(input())
graph = {}
ans = []
for i in range(n):
    t = list(map(int, input().split()))
    v = t[0]
    k = t[1]
    graph[v] = [t[i+2] for i in range(k)]
    ans.append([v,None,None])

class Time:
    def __init__(self):
        self.time = 0
    def getTime(self):
        self.time += 1
        return self.time

t = Time()

def dfs(graph, target):
    # ???????????????????¨????
    if ans[target - 1][1] is None:
        ans[target - 1][1] = t.getTime()
    if graph[target] == []:
        if ans[target - 1][2] is None:
            ans[target - 1][2] = t.getTime()        
        return
    for v in sorted(graph[target]):
        # # ???????????????????¨????        
        if ans[v - 1][1] is None:
            ans[v - 1][1] = t.getTime()        
        dfs(graph,v)
    if ans[target - 1][2] is None:
        ans[target - 1][2] = t.getTime()

dfs(graph, 1)
for row in ans:
    print(*row)

Python: def dfs(v):  # vを訪問する
    global time
    seen[v] = 1
    start[v] = time
    time += 1

    for next_v in graph[v]:
        if seen[next_v]: continue
        dfs(next_v)
    
    end[v] = time
    time += 1


n = int(input())
graph = []
for _ in range(n):
    line = list(map(int, input().split()))
    graph.append([v - 1 for v in line[2:]])

seen = [0] * n  # 0: 未訪問、1: 訪問済
start = [0] * n
end = [0] * n
time = 1

for v in range(n):
    if not seen[v]: dfs(v)

for i in range(n):
    print(i+1, start[i], end[i])

Python: n=int(input())
seen=[-1]*n
first_order=[0]*n
last_order=[0]*n
cnt=0
def dfs(G,s):
    global cnt
    first_order[s]=cnt+1
    cnt+=1
    seen[s]=1
    for nv in G[s]:
        if(seen[nv]!=-1):
            continue
        dfs(G,nv)
    last_order[s]=cnt+1
    cnt+=1

G=[[] for i in range(n)]
for i in range(n):
    li=list(map(int,input().split()))
    for x in range(2,len(li)):
        G[i].append(li[x]-1)
for i in range(n):
    if(seen[i]==-1):
        dfs(G,i)
for i in range(n):
    print(i+1,first_order[i],last_order[i])

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

Python: # coding: utf-8
timestamp = 1

stack = []
indata = []
visit = []      #?¨?????¨????
visitTime = []  #?¨???????????¨??????¨
lastTimeStack = []      #?¨?????????????????¨??????¨


def inputdata():
    global      visit
    global      indata
    global      visitTime

    n = int(input().rstrip())

    for i in range(n):
        visit.append(True)
        visitTime.append([0, 0])

        lst = [int(i) for i in input().rstrip().split(" ")]
        k = lst[1]
        v = []
        for j in range(k):
            v.append(lst[2 + j] - 1)
        indata.append(v)

def procV(n):
    global lastTimeStack
    global timestamp
    global visit
    global stack

    if visit[n]:
        stack.append(n)
        lastTimeStack.append(n)
        visitTime[n][0] = timestamp
        timestamp += 1
        visit[n] = False
    else:
        if visitTime[n][1] == 0:
            visitTime[n][1] = timestamp
            timestamp += 1

"""
main
"""
inputdata()
stack.append(0)             #?????????????´????push??????

while True:
    if len(stack) == 0:
        isNotVisit = True
        n = 0
        for i in visit:
            if i:
                isNotVisit = False
                stack.append(n)
                break
            n += 1
        if isNotVisit:
            break

    n = stack.pop()         #??????????????????pop??????
    procV(n)                #pop????????????????????????????????????

    #???????????¢???
    for i in reversed(indata[n]):
        if visit[i]:
            hasNotChildAdd = False
            stack.append(i)

i = 1
for val in visitTime:
    li = [i, val[0], val[1]]
    print(' '.join(map(str, li)))
    i += 1