Go: package main

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

const (
	initialBufSize = 100000
	maxBufSize     = 1000000
)

var sc *bufio.Scanner

func initScanner(r io.Reader) *bufio.Scanner {
	buf := make([]byte, initialBufSize)

	sc := bufio.NewScanner(r)
	sc.Buffer(buf, maxBufSize)
	sc.Split(bufio.ScanWords) // bufio.ScanLines
	return sc
}

func main() {
	sc = initScanner(os.Stdin)
	resolve(parseProblem())
}

type graph struct {
	size  int
	edges [][]int
}

func parseProblem() *graph {
	n := scanInt(sc)
	g := &graph{
		size:  n,
		edges: make([][]int, n),
	}
	for i := 0; i < g.size; i++ {
		_ = scanInt(sc)
		k := scanInt(sc)
		g.edges[i] = make([]int, k)
		for j := 0; j < k; j++ {
			g.edges[i][j] = scanInt(sc) - 1
		}
	}
	return g
}

func resolve(g *graph) {
	ds := make([]int, g.size)
	fs := make([]int, g.size)
	time := 0
	for i := 0; i < len(ds); i++ {
		if ds[i] == 0 {
			time++
			time = _dfs(ds, fs, time, g, i)
		}
	}
	for i := 0; i < len(ds); i++ {
		fmt.Println(i+1, ds[i], fs[i])
	}
	return
}

func _dfs(ds, fs []int, time int, g *graph, idx int) int {
	ds[idx] = time
	for _, next := range g.edges[idx] {
		if ds[next] > 0 {
			continue
		}
		time++
		time = _dfs(ds, fs, time, g, next)
	}
	time++
	fs[idx] = time
	return time
}

// snip-scan-funcs
func scanInt(sc *bufio.Scanner) int {
	sc.Scan()
	i, _ := strconv.Atoi(sc.Text())
	return int(i)
}
func scanString(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

Python: import sys
n = int(input())
input_line = [[int(i) for i in str.split()] for str in sys.stdin.read().splitlines()]
for i in range(n):
    input_line[i] = [] if len(input_line[i]) == 2 else input_line[i][2:]
detect_time = [0] * n
finish_time = [0] * n
is_visit = [False] * n
stack = []
time = 0

while(time < n*2):
    time += 1
    id = is_visit.index(False) + 1
    stack.append(id)
    is_visit[id-1] = True
    detect_time[id-1] = time
    while(len(stack) != 0):
        id = stack[-1]
        if len(input_line[id-1]) == 0:
            time += 1
            finish_time[stack.pop()-1] = time
        else:
            detect_id = input_line[id-1].pop(0)
            if is_visit[detect_id-1]:
                continue
            stack.append(detect_id)
            time += 1
            detect_time[detect_id-1] = time
            is_visit[detect_id-1] = True


for id in range(n):
    print('{0} {1} {2}'.format(id+1, detect_time[id], finish_time[id]))

Python: 
def DFS(n = 1, i = 0, time = 1):
    for j in range(n):
        if A[i][j] == 1 and d[j] == 0:
            time = time + 1
            d[j] = time
            time = DFS(n, j, time)
    time = time + 1
    f[i] = time
    return time

n = int(raw_input())
A = [0] * n
for i in range(n):
    A[i] = [0] * n

for i in range(n):
    value = map(int, raw_input().split())
    u = value[0] - 1
    k = value[1]
    nodes = value[2:]
    for j in range(k):
        v = nodes[j] - 1
        A[u][v] = 1

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

time = 0
for i in range(n):
    if d[i] == 0:
        time = time + 1
        d[i] = time
        time = DFS(n, i, time)

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

Python: WHITE = 0
GRAY = 1
BLACK = 2

n = int(input())

M = [[0] * n for i in range(n)]

d = [0] * (n)
f = [0] * (n)
color = [WHITE] * (n)


time = 0

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

def dfs():
    for u in range(n):
        if color[u] == WHITE:
            dfs_visit(u)

    for u in range(n):
        print("{} {} {}".format(u+1, d[u], f[u]))


if __name__ == "__main__":
    for i in range(n):
        arr = list(map(int, input().split()))
        for v in (arr[2:]):
            M[arr[0]-1][v-1] = 1

    dfs()

Python: #coding:utf-8
from copy import deepcopy

n = int(input())
c = ["white" for i in range(n)]
d = [0 for i in range(n)]
f = [0 for i in range(n)]
S = []
class DFS:
    def __init__(self, key, color="white",nex=None):
        self.color = color
        self.nex = nex
        self.key = key

objList = [DFS(i+1) for i in range(n)]
for i in range(n):
    data = list(map(int,input().split()))
    times = data[1]
    obj = objList[i]
    for j in range(times):
        index = data[2+j] - 1
        nextobj = DFS(index+1)
        obj.nex = nextobj
        obj = obj.nex


time = 1
def check(first,time):
    obj = objList[first]
    c[first] = "gray"
    d[first] = time
    f[first] = time
    S.append(first+1)
    
    while S != []:
        index = S[-1] - 1
        u = objList[index]
        v = u.nex
    
        if v != None:
            objList[index] = v
            if c[v.key - 1] == "white":
                index = v.key - 1
                v = objList[index]
                c[v.key-1] = "gray"
                time += 1
                d[index] = time
                S.append(v.key)

           
                
        else:
            S.pop()
            c[u.key-1] = "black"
            time += 1
            f[index] = time
    return time


for i in range(n):
    if f[i] == 0:
        time = check(i,time) + 1
        

k = 1
for i,j in zip(d,f):
    print(k,i,j)
    k += 1

Python: import sys

sys.setrecursionlimit(10 ** 8)
n = int(input())

graph = [[] for _ in range(n)]
for i in range(n):
    graph[i] = list(map(lambda x: x - 1, list(map(int, input().split()))[2:]))

timestamp = [[] for _ in range(n)]
visited = [False] * n
cnt = 0


def dfs(v):
    global visited
    global cnt
    global timestamp
    cnt += 1
    timestamp[v].append(cnt)
    visited[v] = True
    for to in graph[v]:
        if visited[to]:
            continue
        else:
            dfs(to)
    cnt += 1
    timestamp[v].append(cnt)


dfs(0)

while False in visited:
    nxt = visited.index(False)
    dfs(nxt)


for i, (d, f) in enumerate(timestamp, 1):
    print(i, d, f)

Python: n = int(input())
vert = [[0,0]+list(map(int,range(1,n+1)))]
parents = [0]
now = 0
time = 0
for i in range(n):
    ukv = list(map(int,input().split()))
    vert.append([0,0]+ukv[2:])
while(parents):
    for i in range(2,len(vert[now])):
        if vert[vert[now][i]][0] == 0:
            parents.append(now)
            now = vert[now][i]
            time += 1
            vert[now][0] = time
            break
    else:
        if now != 0:
            time += 1
        vert[now][1] = time
        now = parents.pop()
for i in range(1,n+1):
    print(i,*vert[i][0:2])

Python: 
def DFS(A = [0], i = 0, d = [0], f = [0], time = 1):
    for j in range(len(d)):
        if A[i][j] == 1 and d[j] == 0:
            time = time + 1
            d[j] = time
            time = DFS(A, j, d, f, time)
    time = time + 1
    f[i] = time
    return time

n = int(raw_input())
A = [0] * n
for i in range(n):
    A[i] = [0] * n

for i in range(n):
    value = map(int, raw_input().split())
    u = value[0] - 1
    k = value[1]
    nodes = value[2:]
    for j in range(k):
        v = nodes[j] - 1
        A[u][v] = 1

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

time = 0
for i in range(n):
    if d[i] == 0:
        time = time + 1
        d[i] = time
        time = DFS(A, i, d, f, time)

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

Python: def dfs(adjlist,v):
    global d,f,t
    d[v-1]=t
    t+=1
    for node in adjlist[v-1]:
        if d[node-1]<0 and node>0:
            dfs(adjlist,node)
    f[v-1]=t
    t+=1

n=int(input())
adjlist=[list(map(int,input().split()))[2:] for _ in range(n)]
d=[-1]*n
f=[-1]*n
t=1
for i in range(1,n):
    if d[i-1]<0:
       dfs(adjlist,i)
for i in range(n):
    print("{} {} {}".format(i+1,d[i],f[i]))