Go: package main

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

func main() {
	scn := bufio.NewScanner(os.Stdin)
	scn.Split(bufio.ScanWords)
	nextInt := func() int { scn.Scan(); r, _ := strconv.Atoi(scn.Text()); return r }
	w := bufio.NewWriter(os.Stdout)

	n := nextInt()
	vecs := make([][]int, n)
	for i := 0; i < n; i++ {
		u := nextInt()
		k := nextInt()
		for j := 0; j < k; j++ {
			vecs[u-1] = append(vecs[u-1], nextInt()-1)
		}
	}

	ds := make([]int, n)
	fs := make([]int, n)
	founds := make([]bool, n)
	t := 0
	for i := range founds {
		if !founds[i] {
			t = dfs(vecs, ds, fs, founds, i, t)
		}
	}

	for i := 0; i < n; i++ {
		fmt.Fprintln(w, i+1, ds[i], fs[i])
	}

	w.Flush()
}

func dfs(vecs [][]int, ds, fs []int, founds []bool, i, t int) (time int) {
	t++
	ds[i] = t
	founds[i] = true
	for _, v := range vecs[i] {
		if !founds[v] {
			t = dfs(vecs, ds, fs, founds, v, t)
		}
	}
	t++
	fs[i] = t

	return t
}

Python: def dfs(i,a,d,f,t):
    if d[i-1]:
        return t
    d[i-1] = t
    t += 1
    for j in a[i-1]:
        t = dfs(j,a,d,f,t)
    f[i-1] = t
    t += 1
    return t
 
if __name__ == "__main__":
    n = int(input())
    a = []
    for i in range(n):
        a.append(list(map(int,input().split()))[2:])
    d = [0]*n
    f = [0]*n
    t = 1
    for i in range(n):
        if d[i] == 0:
            t = dfs(i+1,a,d,f,t)
    for i in range(n):
        print(i+1,d[i],f[i])

Python: """Depth First Search."""

n = int(input())

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

# searched or not, number of vertex, discovery time and finishing time
sndf = [None]
for i in range(1, n + 1):
    sndf.append([False, i])

path = []

def dfs(u):
    time = 0
    path.append(u)
    time += 1
    sndf[u].append(time)

    while path:
        u = path[-1]
        if adj[u]:
            v = adj[u].pop(0)
            if not sndf[v][0]:
                time += 1
                sndf[v].append(time)
                path.append(v)
        else:
            path.pop()
            sndf[u][0] = True
            time += 1
            sndf[u].append(time)


dfs(1)

for x in sndf[1:]:
    print(*x[1:])

Python: import sys

n = int(sys.stdin.readline())+1

m = [[0] * n for _ in range(n)]
discover_time = [-1] * n
finish_time = [0] * n
clock = -1

def walk(p):
    global clock
    clock += 1

    for i in range(n):
        if m[p][i]==0: continue
        if discover_time[i]<0:
            discover_time[i] = clock
            clock = walk(i)
            finish_time[i] = clock
            clock +=1

    return clock

m[0] = [1] * n
for i in range(1,n):
    cols = list(map(int, sys.stdin.readline().split()))
    for j in cols[2:]:
        m[i][j]=1

walk(0)

for i in range(1,n):
    print(i,discover_time[i],finish_time[i])

Python: 
# ??±???????????¢?´¢(Depth First Search)

def DFS(n = 1, A = [0], i = 0, d = [0], f = [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, 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 i in range(k):
        v = nodes[i] - 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, A, i, d, f, time)

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

Python: T = [0]

def curserch(N,k,T,P,n):
    T[0] = T[0]+1
    P[k]["d"] = T[0]
    for i in range(1,n+1):
        if N[k][i]==1 and P[i]["d"]==0:
            curserch(N,i,T,P,n)
            T[0] = T[0]+1
            P[i]["f"]=T[0]


n = int(input())
A = [[0 for j in range(n+1)] for i in range(n+1)]


for i in range(n):
    vec = input().split()
    u = int(vec[0])
    k = int(vec[1])
    nodes = vec[2:]
    for i in range(int(k)):
        v = int(nodes[i])
        A[u][v] = 1

P=[{"d":0} for i in range(n+1)]
for i in range(1,n+1):
    if P[i]["d"]==0:
        curserch(A,i,T,P,n)
        T[0] = T[0]+1
        P[i]["f"]=T[0]
for i in range(1,n+1):
    print(i,P[i]["d"],P[i]["f"])

Python: #16D8101014F KurumeRyunosuke 2018/6/20

n=int(input())
ls=[[0 for i in range(n)]for j in range(n)]
for i in range(n):
	tmp=input().split()
	for j in range(int(tmp[1])):
		ls[i][int(tmp[j+2])-1]=1

"""
for i in range(n):
    for j in range(n):
        if(j!=n-1):
            print(int(ls[i][j]), end=' ')
        else:
            print(int(ls[i][j]))
"""
stuck=[0]
count=1
d=[0 for i in range(n)]
f=[0 for i in range(n)]
d[0]=count
while True:
	count+=1
	p=0
	for i in range(n):
		if ls[stuck[len(stuck)-1]][i] is not 0:
			ls[stuck[len(stuck)-1]][i]=0
			
			p=1
			#print(stuck)
			stuck.append(i)
			d[stuck[len(stuck)-1]]=count
			break

	if p is 1:
		for i in range(n):
			ls[i][stuck[len(stuck)-1]]=0
	if p is 0:
		#print("//")
		a=stuck.pop()
		f[a]=count
		for i in range(n):
			ls[a][i]=0

	if len(stuck) is 0:
		t=0
		for i in range(n):
			for j in range(n):
				if ls[i][j] is not 0 and t is 0:
					count+=1
					stuck.append(i)
					d[stuck[len(stuck)-1]]=count
					#print(i)
					t=1
					
		if t is 0:
			break
		#print("break")

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

Python: n=0
t=1
def adjacent_matrix():
    global n
    n=int(input())
    v=[]
    array=[]
    for i in range(n):
        zero=[0 for i in range(n)]
        a=list(map(int,input().split()))
        a=a[2:]
        for j in a:
            zero[j-1]=1
        array.append(zero)
    return array
def dfs(array,i,d,f):
    global t
    if i == n:
        return
    else:
        if(d[i] == 0):
            d[i] = t
            t += 1
            for (j,x) in enumerate(array[i]):
                if x == 1:
                    dfs(array,j,d,f)
            f[i] = t
            t += 1
    return 


def main():
    array=adjacent_matrix()
    print()
    d=[0 for i in range(n)]
    f=[0 for i in range(n)]
    for i in range(n):
        dfs(array,i,d,f)
    for i in range(n):
        print("{} {} {}".format(i+1,d[i],f[i]))

if __name__ == "__main__":
    main()

Python: N=int(input())
L=[[10**9]for i in range(N+1)]
for i in range(N):
    l=list(map(int,input().split()))
    for j in range(l[1]):
        L[i+1].append(l[2+j])
#print(L)
for i in range(N+1):
    L[i].sort(reverse=True)
    
#print(L)
ans=[]
for i in range(N+1):
    ans.append([0,0])


from collections import deque 

Q=deque()
cnt=1
for i in range(N):
    Q.append([0,N-i])
for i in range(10**7):

    if len(Q)==0:
        break
    q0,q1=Q.pop()
    #print(q0,q1)
    if q1!=10**9:
        if ans[q1][0]==0:
            ans[q1][0]=cnt
            cnt+=1
            for j in L[q1]:
                Q.append([q1,j])
    else:
        ans[q0][1]=cnt
        cnt+=1
    #print(ans,Q)
for i in range(1,N+1):
    print(i,ans[i][0],ans[i][1])

Python: from sys import stdin
from collections import deque

def read_graph(n):
    A = [ [0]*(n+1) for _ in range(n+1) ]
    for _ in range(n):
        line = deque(stdin.readline().strip().split())
        i = line.popleft()
        line.popleft()
        for k in line:
            A[int(i)][int(k)] = 1
    return A

def dfs_ctrl(n, A):
    color = ["WHITE"] * (n+1)
    d = [0] * (n+1)
    f = [0] * (n+1)
    time = 0

    def dfs(u):
        nonlocal color
        nonlocal time
        if color[u] == "WHITE":
            color[u] = "GRAY"
            time += 1
            d[u] = time

            for v in range(1, n+1):
                if A[u][v] and color[v] == "WHITE":
                    dfs(v)
            color[u] = "BLACK"
            time += 1
            f[u] = time

    for i in range(1, n+1):
        if color[i] == "WHITE":
            dfs(i)

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

n = int(input())
A = read_graph(n)
dfs_ctrl(n, A)