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)
	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: from sys import setrecursionlimit

setrecursionlimit(10 ** 9)

n = int(input())

graph = []

for _ in range(n):
    tmp = list(map(int, input().split()))

    if tmp[1] == 0:
        graph.append([])
        continue
    else:
        graph.append(list(map(lambda x: x - 1, tmp[2: tmp[1] + 2])))

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

time = 1


def dfs(x):
    if d[x] != -1:
        return

    global time

    d[x] = time
    time += 1

    for n in graph[x]:
        dfs(n)

    f[x] = time
    time += 1


for i in range(n):
    dfs(i)

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

Python: n = int(input())
A = [[0 for j in range(n)] for i in range(n)]
for i in range(n):
    arr = list(map(int, input().split(' ')))
    u, k, v = arr[0], arr[1], arr[2:]
    for j in range(k):
        A[u-1][v[j]-1] = 1

hist_stack = [0]
time_hist = [0]

vert_hist = [[] for i in range(n)]
vert_hist[0].append(1)
time = 2
while True:
    flag = False
    if len(hist_stack) == 0: break
    for j in range(n):
        if A[hist_stack[-1]][j] == 1 and j not in time_hist:
            hist_stack.append(j)
            time_hist.append(j)
            vert_hist[j].append(time)
            flag = True
            break
    if not flag:
        j = hist_stack.pop()
        time_hist.append(j)
        vert_hist[j].append(time)
    time += 1

for i in range(n):
    print(i+1, ' '.join(list(map(str, vert_hist[i]))))

Python: #coding:utf-8

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

S.append(1)
obj = objList[0]
obj.color = "gray"
d[0] = 1
f[0] = 1
c[0] = "gray"

time = 1
while S != []:
    index = S[-1] - 1
    u = objList[index]
    v = u.nex

    time += 1
    if v != None and c[v.key - 1] == "white":
        objList[index] = v
        index = v.key - 1
        v = objList[index]
        c[v.key-1] = "gray"
        d[index] = time
        S.append(v.key)
        
    else:
        S.pop()
        c[u.key-1] = "black"
        f[index] = time

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

Python: N = int(input())

E = [None] * (N+1)
for _ in range(N):
    u, k, *vs = list(map(int, input().split()))
    E[u] = vs

d = [0] * (N+1)
f = [0] * (N+1)
t = 0

def dfs(v):
    global t, d, f
    if d[v]:
        return
    t += 1
    d[v] = t
    for u in E[v]:
        dfs(u)
    t += 1
    f[v] = t

for v in range(1, N+1):
    dfs(v)

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

Python: 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 = []

time = 0

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

    for v in adj[u]:
        if not sndf[v][0]:
            dfs(v)
    sndf[u][0] = True
    time += 1
    sndf[u].append(time)


for i in range(1, n + 1):
    if not sndf[i][0]:
        dfs(i)

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

Python: #!usr/bin/env python3
from collections import defaultdict,deque
from heapq import heappush, heappop
from itertools import permutations
import sys
import math
import bisect
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def I(): return int(sys.stdin.readline())
def LS():return [list(x) for x in sys.stdin.readline().split()]
def S():
    res = list(sys.stdin.readline())
    if res[-1] == "\n":
        return res[:-1]
    return res
def IR(n):
    return [I() for i in range(n)]
def LIR(n):
    return [LI() for i in range(n)]
def SR(n):
    return [S() for i in range(n)]
def LSR(n):
    return [LS() for i in range(n)]

sys.setrecursionlimit(1000000)
mod = 1000000007

cnt = 1
def solve():
    global cnt
    def dfs(x):
        global cnt
        f[x] = cnt
        for y in v[x]:
            if not d[y]:
                d[y] = cnt
                cnt += 1
                dfs(y)
        f[x] = cnt
        cnt += 1

    n = I()
    v = []
    for i in range(n):
        e = LI()
        u = e[2:]
        for i in range(len(u)):
            u[i] -= 1
        v.append(u)
    d = [0]*n
    f = [0]*n
    for i in range(n):
        if not d[i]:
            d[i] = cnt
            cnt += 1
            dfs(i)
    for i in range(n):
        print(i+1,d[i],f[i])
    return

#Solve
if __name__ == "__main__":
    solve()

Python: n=int(input())
edge=[[] for _ in range(n+1)]
for i in range(n):
  v,k,*u=list(map(int,input().split()))
  edge[v]=u
d=[0]*(n+1)
f=[0]*(n+1)
def dfs(now,t):
  d[now]=t
  vis.append(now)
  for i in edge[now]:
    if i not in vis:
      t=dfs(i,t+1)
  f[now]=t+1
  return t+1
vis=[]
t=1
for i in range(1,n+1):
  if i not in vis:
    t=dfs(i,t)+1
for i in range(1,n+1):
  print(i,d[i],f[i])