Go: package main

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

type vertexId int

type vertex struct {
	id vertexId
	firstVisitAt int
	finishVisitAt int
	adjs []vertexId
}

func createVertex(id int, adjsInt []int) vertex {
	adjs := make([]vertexId, len(adjsInt))
	for i := 0; i < len(adjs); i++ {
		adjs[i] = vertexId(adjsInt[i])
	}
	return vertex{
		id: vertexId(id),
		firstVisitAt: 0,
		finishVisitAt: 0,
		adjs: adjs,
	}
}

func (v *vertex) doesAllAdjsVisited(vertices []vertex) bool {
	for _, vId := range v.adjs {
		adj := vertices[vId-1]
		if !adj.isVisited() {
			return false
		}
	}
	return true
}

func (v *vertex) isFirstVisit() bool {
	return v.firstVisitAt == 0
}

func (v *vertex) isVisited() bool {
	return v.firstVisitAt > 0
}

func (v *vertex) nextVertex(vertices []vertex) (vertexId, error) {
	for _, vId := range v.adjs {
		adj := vertices[vId-1]
		if !adj.isVisited() {
			return vId, nil
		}
	}
	return vertexId(-1), fmt.Errorf("illegal")
}

func dfs(currentId vertexId, timestamp int, vertices []vertex) int {
	timestamp = timestamp + 1
	currentVertex := &vertices[currentId-1]
	if currentVertex.isFirstVisit() {
		currentVertex.firstVisitAt = timestamp
	}
	for !currentVertex.doesAllAdjsVisited(vertices) {
		nextVertexId, _ := currentVertex.nextVertex(vertices)
		timestamp = dfs(nextVertexId, timestamp, vertices)
	}
	timestamp = timestamp + 1
	currentVertex.finishVisitAt = timestamp
	return timestamp
}

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	n, err := nextInt(sc)
	if err != nil {
		panic(err)
	}

	vertices := make([]vertex, n)
	for i := 0; i < n; i++ {
		id, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjN, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjs := make([]int, adjN)
		for j := 0; j < adjN; j++ {
			adjId, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			adjs[j] = adjId
		}
		vertices[i] = createVertex(id, adjs)
	}

	dfs(vertexId(1), 0, vertices)

	for i := 0; i < n; i++ {
		fmt.Printf("%d %d %d\n", vertices[i].id, vertices[i].firstVisitAt, vertices[i].finishVisitAt)
	}
}

func nextText(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

func nextInt(sc *bufio.Scanner) (int, error) {
	return strconv.Atoi(nextText(sc))
}

Python: n = int(input())

class Node:
    def __init__(self, idd, neighbors):
        self.idd = idd
        self.neighbors = neighbors
        self.foundAt = 0
        self.completeAt = 0
        
    def __repr__(self):
        return "{0} {1} {2}".format(self.idd, self.foundAt, self.completeAt)

Nodes = [None] * n
for i in range(n):
    row = [int(tt) for tt in input().split()]
    Nodes[row[0]-1] = Node(row[0], [ row[j + 2] for j in range(row[1])])
        
def depthSearch(Nodes):
    stack = [Nodes[0]]
    
    time = 2
    current = stack[-1]
    current.foundAt = 1
    while len(stack) > 0 or any([node.foundAt==0 for node in Nodes]):
        if(len(stack)==0):
            newStart = [node for node in Nodes if node.foundAt==0][0]
            newStart.foundAt = time
            stack.append(newStart)
            time += 1
        current = stack[-1]
        if(len(current.neighbors) > 0):
            next_n = Nodes[current.neighbors.pop(0)-1]
            if(next_n.foundAt != 0):
                continue
            next_n.foundAt = time
            stack.append(next_n)
        else:
            current.completeAt = time
            stack.pop(-1)
        time += 1
    return Nodes
Nodes = depthSearch(Nodes)
for node in Nodes:
    print(node)

Python: 
n=int(input())
used=[False for i in range(n)]
d=[0 for i in range(n)]
f=[0 for i in range(n)]
mat=[]
for i in range(n):
    tmp=list(map(int,input().split()))
    mat.append(tmp[2:])

t=1
def dfs(now):
    global t
    if used[now]:
        return
    else:
        used[now]=True
    d[now]=t
    t+=1
    for i in range(len(mat[now])):
        dfs(mat[now][i]-1)
    f[now]=t
    t+=1

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

Python: # -*- coding: utf-8 -*-
N = int(input())
adj = [[0]*N for _ in range(N)]
searched = {n: 0 for n in range(N)}
edge = {}

def find_all(list_, x, j=-1):
    return [i for i, n in enumerate(list_) if n==1 and n != j]


for n in range(N):
    inp = list(map(int, input().split()))
    edge[n] = inp[1]
    for i in inp[2:]:
        adj[inp[0]-1][i-1] = 1

time = 1
stack = []
unsearch = set(range(N))
uncomplete = set(range(N))
result = {n:{"found": 0, "finish": 0} for n in range(N)}

while len(unsearch) > 0 or len(stack) > 0:
    if len(stack) == 0:
        i = min(unsearch)
        result[i]["found"] = time
        unsearch.remove(i)
        time += 1

    
    while True:
        j = i
        for n in sorted(unsearch):
            if adj[i][n] == 1:
                j = n
                result[n]["found"] = time
                unsearch.remove(n)
                stack.append(i)
                time += 1
                break

        if i == j:
            result[i]["finish"] = time
    
            if len(stack) != 0:                
                i = stack.pop()
                time += 1
            else:
                break
        else:
            i = j
                
for n in range(N):
    print("{} {} {}".format(n, result[n]["found"], result[n]["finish"]))

Python: n = int(input())
g = [None] * n
visited = [0] * n
root = set(range(n))
ts = [[0, 0] for _ in range(n)]
t = 1

while n:
    l = list(map(int, input().split()))
    connected = [i - 1 for i in l[2:]]
    g[l[0] - 1] = [i - 1 for i in l[2:]]
    root -= set(connected)
    n -= 1


def dfs(i):
    global g, t, ts, visited
    lts = ts[i]
    lts[0] = t
    visited[i] = 1
    for c in g[i]:
        if not visited[c]:
            t += 1
            dfs(c)
    t += 1
    lts[1] = t


for r in sorted(root):
    dfs(r)

for i, v in enumerate(ts):
    print(i + 1, *v)

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:
		#print("break")
		break

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

Python: #!/usr/bin/env python
# -*- coding:utf-8 -*-
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()