Go: package main

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

// I/O
type Scanner struct {
	sc *bufio.Scanner
}

func NewScanner() *Scanner {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)
	sc.Buffer(make([]byte, 1024), int(1e+9))
	return &Scanner{sc}
}

func (s *Scanner) nextStr() string {
	s.sc.Scan()
	return s.sc.Text()
}

func (s *Scanner) nextInt() int {
	i, e := strconv.Atoi(s.nextStr())
	if e != nil {
		panic(e)
	}
	return i
}

func (s *Scanner) nextFloat() float64 {
	f, e := strconv.ParseFloat(s.nextStr(), 64)
	if e != nil {
		panic(e)
	}
	return f
}

func (s *Scanner) nextRuneSlice() []rune {
	return []rune(s.nextStr())
}

func (s *Scanner) nextIntSlice(n int) []int {
	res := make([]int, n)
	for i := 0; i < n; i++ {
		res[i] = s.nextInt()
	}
	return res
}

func (s *Scanner) nextFloatSlice(n int) []float64 {
	res := make([]float64, n)
	for i := 0; i < n; i++ {
		res[i] = s.nextFloat()
	}
	return res
}

// Arithmetic
func max(nums ...int) int {
	m := nums[0]
	for _, i := range nums {
		if m < i {
			m = i
		}
	}
	return m
}

func min(nums ...int) int {
	m := nums[0]
	for _, i := range nums {
		if m > i {
			m = i
		}
	}
	return m
}

func abs(x int) int {
	if x > 0 {
		return x
	}
	return -x
}

func pow(x, y int) int {
	res := 1
	for i := 0; i < y; i++ {
		res *= x
	}
	return res
}

func ceil(a, b int) int {
	if a%b == 0 {
		return a / b
	} else {
		return a/b + 1
	}
}

// Sort
type RuneSlice []rune

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

// Main
func main() {
	sc := NewScanner()
	wtr := bufio.NewWriter(os.Stdout)
	N := sc.nextInt()
	G := make([][]int, N)
	for i := 0; i < N; i++ {
		u, k := sc.nextInt()-1, sc.nextInt()
		for j := 0; j < k; j++ {
			G[u] = append(G[u], sc.nextInt()-1)
		}
	}
	ans := make([][2]int, N)
	time := 0
	found := make(map[int]bool)
	var dfs func(cur int)
	dfs = func(cur int) {
		time++
		ans[cur][0] = time
		found[cur] = true
		for i := 0; i < len(G[cur]); i++ {
			next := G[cur][i]
			if !found[next] {
				dfs(G[cur][i])
			}
		}
		time++
		ans[cur][1] = time
	}
	for i := 0; i < N; i++ {
		if !found[i] {
			dfs(i)
		}
	}

	for i := 0; i < N; i++ {
		fmt.Fprint(wtr, i+1)
		for j := 0; j < 2; j++ {
			fmt.Fprint(wtr, " ")
			fmt.Fprint(wtr, ans[i][j])
		}
		fmt.Fprintln(wtr)
	}
	wtr.Flush()
}

Python: WHITE = 0
GRAY = 1
BLACK = 2
color, d, f = [WHITE for i in range(n)]
t = 1

def visit(u):
    color[u] = GRAY
    d[u] += t
    t += 1
    for v in range(n):
        if (M[u-1][v-1] == 0):
            continue
        if (color[v] == WHITE):
            visit(v)
    color[u] = BLACK
    f[u] = t
    t += 1

for u in range(n):
    if (color[u] == WHITE):
        visit(u)
for i in range(n):
    print(str(i+1), str(d[i]), str(f[i]), sep = " ")

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

Python: n = int(input())
graph = {}

for i in range(1, n + 1):
    data = input().split()
    graph[i] = [int(i) for i in data[2:]]


class dfs:
    def __init__(self, graph):
        self.g = graph
        self.visited = set()
        self.time = 0
        self.res = {}

    def dfs(self, cur):
        self.visited.add(cur)
        self.time += 1
        start = self.time
        for node in self.g[cur]:
            if node not in self.visited:
                self.dfs(node)
        self.time += 1
        end = self.time
        self.res[cur] = (start, end)


solver = dfs(graph)
for i in range(1, n + 1):
    if i not in solver.visited:
        solver.dfs(i)

for i in range(1, n + 1):
    print(i, solver.res[i][0], solver.res[i][1])

Python: N = int(input())

nodes = [tuple(map(int, input().split(' '))) for _ in range(N)]
d = [-1 for _ in range(N + 1)]
f = [-1 for _ in range(N + 1)]

clock = 0


def dfs(node):
    global clock
    if d[node] == -1:
        clock += 1
        d[node] = clock
    neighbors = sorted(nodes[node - 1][2:])

    for neighbor in neighbors:
        if d[neighbor] == -1:
            dfs(neighbor)

    if f[node] == -1:
        clock += 1
        f[node] = clock


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

Python: n = int(input())
mat = [[0] * n for _ in range(n)]
d, f = [0] * n, [0] * n
for _ in range(n):
    adj = list(map(int, input().split()))
    i = adj[0]
    v = adj[2:]
    for j in v:
        mat[i - 1][j - 1] = 1

time, current = 1, 0
stack = []
d[current] = time
while 0 in f:
    if not stack:
        stack.append(0)
    time += 1
    current = stack[-1]
    for i in range(len(mat[current])):
        if mat[current][i] and not d[i]:
            current = i
            d[i] = time
            stack.append(i)
            break
    else:
        f[current] = time
        current = stack.pop()

for l in zip(range(1, n + 1), d, f):
    print(*l)

Python: from collections import defaultdict


def dfs(v, t):
    if start[v] == 0:
        start[v] = t
        t += 1
    else:
        return t

    for nv in graph[v]:
        t = dfs(nv, t)

    end[v] = t
    t += 1

    return t


n = int(input())

graph = defaultdict(list)

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

start = [0] * (n + 1)
end = [0] * (n + 1)


t = 1

for i in range(1, n + 1):
    t = dfs(i, t)

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

Python: 
d = None
f = None


def dfs(g, cur, time):
    global d, f
    d[cur] = time
    for next in g[cur]:
        if d[next] == 0:
            time = dfs(g, next, time+1)
    f[cur] = time + 1
    return time + 1


def main():
    global d, f
    n = int(input())
    g = [[] for _ in range(n)]
    d = [0 for _ in range(n)]
    f = [0 for _ in range(n)]
    for _ in range(n):
        inp = list(map(int, input().split()))
        m = inp[0] - 1
        k = inp[1]
        for i in range(k):
            g[m].append(inp[i+2] - 1)
    dfs(g, 0, 1)
    for i in range(n):
        print(i, d[i], f[i])


if __name__ == '__main__':
    main()

Python: from __future__ import division,print_function
import time
import sys
import io
import re
import math
start = time.clock()
i = 0
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(sys.stdin.readline())
    L=[]
    for _ in range(num):
        L.append([int(s) for s in sys.stdin.readline().split()[2:]])
    d=[0]*num
    f=[0]*num
    tm=0
    for i in range(num):
        if not d[i]:
            tm=walk(i,tm,L,d,f)
    for i in range(num):
        print(i+1,d[i],f[i])
 
main()

Python: n = int(input())
A = [[0 for i in range(n)] for j in range(n)]

for i in range(n):
    u, k, *v = list(map(int, input().split()))
    for j in v:
        A[int(u)-1][int(j)-1] = 1
        # A[int(j)-1][int(u)-1] = 1

# for row in A:
#     msg = ' '.join(map(str, row))
#     # print(msg)

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

t = 0
d[0] = t

# recursive


def dfs(u):
    global t
    # print('visit:', str(u), str(t))
    t += 1
    d[u] = t
    for i in range(len(A[u])):
        if A[u][i] == 1 and d[i] == -1:
            dfs(i)
    t += 1
    f[u] = t
            

dfs(0)


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

Python: n=int(input())

v=[[]]*n
for i in range(n):
    tmp=list(map(int,input().split()))
    tmp=[i-1 for i in tmp[2:]]
    v[i]=tmp

time=1
D=[-1 for _ in range(n)]
F=[-1 for _ in range(n)]

def dfs(src):
    global time
    D[src]=time
    time+=1
    for dst in v[src]:
        if D[dst]==-1:#未訪問
            dfs(dst)
    F[src]=time
    time+=1

for root in range(n):
    if D[root]==-1:
        dfs(root)

for i in range(n):
    print(i+1,D[i],F[i])