Go: package main

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

/***************************************************************
stackによる深さ優先探索を実装する。
***************************************************************/

const (
	N     = 100
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

var (
	n            int
	Adj          [N][N]int
	statusColor  [N]int
	discoverTime [N]int
	finishTime   [N]int
	clock        int
	nt           [N]int
)

/***************************************************************
Stackの定義:
- field
	container: ノードの格納されたスライス
	sp: スタックポインタ
- method
	size(): スタックに積まれているノードの個数を返す
	top(): スタックの一番上に積まれているノードを返す
	isEmpty(): スタックが空かどうかを返す
	pop(): スタックの要素をポップし削除する
	push(): スタックに要素を積む
***************************************************************/

type Stack struct {
	container []int
	sp        int
}

func (s *Stack) size() int {
	return len(s.container)
}

func (s *Stack) top() int {
	return s.container[s.sp]
}

func (s *Stack) isEmpty() bool {
	return s.sp == 0
}

func (s *Stack) pop() int {
	_pop := func() {
		s.container = s.container[:len(s.container)-1]
	}
	defer _pop()
	if s.isEmpty() {
		panic("There is no elements in stack!")
	}
	s.sp--
	return s.container[s.sp]
}

func (s *Stack) push(n int) {
	s.sp++
	s.container[s.sp] = n
}

func next(u int) int {
	for v := nt[u]; v < n; v++ {
		nt[u] = v + 1
		if Adj[u][v] == 1 {
			return v
		}
	}
	return -1
}

func _DFS(target int) {
	for i := 0; i < n; i++ {
		nt[i] = 0
	}
	stack := new(Stack)
	stack.container = make([]int, N+1)
	stack.push(target)
	statusColor[target] = GRAY
	clock++
	discoverTime[target] = clock
	for !stack.isEmpty() {
		u := stack.top()
		v := next(u)
		if v != -1 {
			if statusColor[v] == WHITE {
				statusColor[v] = GRAY
				clock++
				discoverTime[v] = clock
				stack.push(v)
			}
		} else {
			stack.pop()
			statusColor[u] = BLACK
			clock++
			finishTime[u] = clock
		}
	}
}

func DFS() {
	for i := 0; i < n; i++ {
		statusColor[i] = WHITE
		nt[i] = 0
	}
	clock = 0
	for i := 0; i < n; i++ {
		if statusColor[i] == WHITE {
			_DFS(i)
		}
	}
	for i := 0; i < n; i++ {
		fmt.Printf("%d %d %d\n", i+1, discoverTime[i], finishTime[i])
	}
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	scanner.Scan()
	n, _ = strconv.Atoi(scanner.Text())
	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			Adj[i][j] = 0
		}
	}
	for i := 0; i < n; i++ {
		scanner.Scan()
		u, _ := strconv.Atoi(scanner.Text())
		scanner.Scan()
		k, _ := strconv.Atoi(scanner.Text())
		u--
		for j := 0; j < k; j++ {
			scanner.Scan()
			v, _ := strconv.Atoi(scanner.Text())
			v--
			Adj[u][v] = 1
		}
	}

	DFS()
}

Python:    #depth first
N=int(input())
V=[]
a=[0]
for i in range(N):
    V.append([int(i) for i in input().split()])
    w=V[i][2:]
    w.sort()
    V[i]=V[i][:2]+w
    a.append(0)
V=sorted(V,key=lambda x:x[0])
c=1
t=1
i=0
r=[1]
a[1]=1
p=[[1,t]]
q=[]
while t<N*2-1:
    j=2
    while t<N*2-1 and j-2<V[i][1] and V[i][1]>0 and a[V[i][j]]==1:
        j+=1
    t+=1
    if j-2<V[i][1]:
        a[V[i][j]]=1
        c+=1
        r.append(V[i][j])
        p.append([V[i][j],t])
        i=V[i][j]-1
    else:
        q.append(p[-1]+[t])
#end time immediately case?
        r.pop(-1)
        p.pop(-1)
        i=r[-1]-1
       # print(q)
q.append([1,1,N*2])
q=sorted(q,key=lambda x:x[0])
for i in range(N):
    for j in range(3):
        q[i][j]=str(q[i][j])
    print(" ".join(q[i]))

Python: def DFS(G):
    ans = [0] + [[0,0,0] for _ in range(len(G))]
    def main(G,i):
        ans[0] += 1
        ans[i] = [i, ans[0], ans[0]]
        for j in sorted(G[i-1][2:]):
            if ans[j][0]==0: main(G,j)
        ans[0] += 1
        ans[i][2] = ans[0]
    main(G,1)
    return ans[1:]


if __name__=='__main__':
    n = int(input())
    G = [list(map(int,input().split())) for _ in range(n)]
    for out in DFS(G): print(*out)

Python: n = int(input())
graph = [[] for _ in range(n)]

global time
global visited 
global f_time 
global e_time 

time = 1
visited = [0 for _ in range(n)]
f_time = [0 for _ in range(n)]
e_time = [0 for _ in range(n)]

def input_graph(n):
  for _ in range(n):
    node_id, num, *v = list(map(int, input().split()))
    for i in range(num):
      graph[node_id-1].append(v[i]-1)

def dfs(node_id):
  global time
  f_time[node_id] = time
  time += 1

  for ad_node in graph[node_id]:
    if visited[ad_node] == 1:
      continue
    visited[ad_node] = 1
    dfs(ad_node)

  e_time[node_id] = time
  time += 1



if __name__ == "__main__":
  input_graph(n)
  for i in range(n):
    if visited[i] == 1:
      continue
    visited[i] = 1
    dfs(i)

  for i, (f, e) in enumerate(zip(f_time, e_time)):
    print(i+1, f, e)

Python: # -*- coding: utf-8 -*-
import sys
INF=10**18
MOD=10**9+7
def input(): return sys.stdin.readline().rstrip()


c=0
def main():
    N=int(input())
    edge=[[] for _ in range(N)]
    for i in range(N):
        l=list(map(lambda x:int(x)-1,input().split()))
        for x in l[2:]:
            edge[i].append(x)
    d=[-1]*N
    f=[-1]*N
    used=[False]*N
    def dfs(v):
        global c
        used[v]=True
        d[v]=c
        for nv in edge[v]:
            if not used[nv]:
                c+=1
                dfs(nv)
        c+=1
        f[v]=c
    global c
    while not all(used):
        for i in range(N):
            if not used[i]:
                c+=1
                dfs(i)

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

if __name__ == '__main__':
    main()

Python: import math,string,itertools,fractions,heapq,collections,re,array,bisect,sys,random,time

sys.setrecursionlimit(10**7)
inf = 10**20
mod = 10**9 + 7

stdin = sys.stdin

ni = lambda: int(ns())
na = lambda: list(map(int, stdin.readline().split()))
ns = lambda: stdin.readline().rstrip()  # ignore trailing spaces

n = ni()
g = []
for i in range(n):
    t = na()
    u = t[0] - 1
    k = t[1]
    v = [x-1 for x in t[2:]]
    g.append(v)
d = [0] * n
f = [0] * n
#print(g)
seen = [False] * n
s = 0
t = 0
def dfs(g, v):
    global t
    #print(v+1, t)
    if seen[v]:
        return
    seen[v] = True
    d[v] = t
    t += 1    
    for next_v in g[v]:
        #if seen[next_v]: continue
        dfs(g, next_v)
    f[v] = t
    t += 1
for i in range(n):
    if len(g[i]) != 0:
        dfs(g, i)
for i in range(n):
    print(i+1, d[i]+1, f[i]+1)

Python: import sys


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


if __name__ == "__main__":
    n = int(sys.stdin.readline())
    color = ["WHITE"] * n
    time = 0
    d = [-1] * n
    f = [-1] * n
    M = [[0] * n for i in range(n)]
    for inp in sys.stdin.readlines():
        inp = list(map(int, inp.split()))
        for i in inp[2:]:
            M[inp[0]-1][i-1] = 1
    dfs(0)
    for i in range(n):
        print(i+1, d[i], f[i])

Python: # https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/11/ALDS1_11_B

G = {}
d = {}
f = {}
used = set()
t = 1


def dfs(cur):
    global G, d, f, t

    used.add(cur)
    d[cur] = t

    for i in G[cur]:
        if i in used:
            continue
        t += 1
        dfs(i)
    t += 1
    f[cur] = t


if __name__ == "__main__":
    N = int(input())

    for _ in range(N):
        u, k, *V = list(map(int, input().split()))
        G[u] = V

    for i in range(1, N+1):
        if i not in used:
            dfs(i)
            t += 1

    for i in G.keys():
        print(i, d[i], f[i])