Go: #include <bits/stdc++.h>
using namespace std;
static const int WHITE = 0;
static const int GRAY  = 1;
static const int BLACK = 2;
static const int N     = 100;

int n, tt;
vector<vector<int>> M(N, vector<int>(N));
vector<int> color(N), d(N), f(N);

void dfs_visit(int u) {
  color[u] = GRAY;
  d[u]     = ++tt;
  for (int v = 0; v < n; v++) {
    if (M[u][v] == 0) continue;
    if (color[v] == WHITE) { dfs_visit(v); }
  }
  color[u] = BLACK;
  f[u]     = ++tt;
}

void dfs() {
  tt = 0;

  for (int u = 0; u < n; u++) {
    if (color[u] == WHITE) dfs_visit(u);
  }
  for (int u = 0; u < n; u++) {
    printf("%d %d %d\n", u + 1, d[u], f[u]);
  }
}

int main() {
  int u, v, k;
  cin >> n;
  for (int i = 0; i < n; i++) {
    cin >> u >> k;
    u--;
    for (int j = 0; j < k; j++) {
      cin >> v;
      v--;
      M[u][v] = 1;
    }
  }

  dfs();
}

Python: # coding: utf-8
import itertools
import math
import bisect

class Node:
    def __init__(self, id, next, rest):
        self.id = id
        self.before = None
        self.next = next
        self.rest = rest
        self.d = None
        self.f = None

    def update_next(self):
        self.next = first(self.rest)
        self.rest = rest(self.rest)


N = int(input())
graph = []
for _ in range(N):
    l = list(map(int, input().split(" ")))
    id = l[0]
    if l[1] != 0:
        next = l[2]
    else:
        next = None
    if l[1] >= 2:
        rest = l[3:]
    else:
        rest = []
    graph.append(Node(l[0], next, rest))

def first(l):
    if l==None:
        return None
    if len(l) == 0:
        return None
    else:
        return l[0]

def rest(l):
    if l == None:
        return None
    if len(l) >= 2:
        return l[1:]
    else:
        return None

def dfs(graph):
    stack = [graph[0]]
    stack[-1].d = 1
    tansakuzumi = [1]
    mitansaku = list(range(1, len(graph)+1))
    res_graph = []
    t = 2
    while len(stack) != 0:
        tansakuzumi.append(stack[-1].id)
        if stack[-1].id in mitansaku:
            mitansaku.remove(stack[-1].id)
        if stack[-1].next == None:
            stack[-1].f = t
            res_graph.append(stack.pop())
            t += 1
        elif stack[-1].next in tansakuzumi:
            stack[-1].update_next()
        else:
            stack.append(graph[stack[-1].next-1])
            stack[-2].update_next()
            stack[-1].d = t
            t += 1
        if len(stack) == 0 and len(mitansaku) >= 1:
            stack.append(graph[mitansaku[0]-1])
            stack[-1].d = t
            t += 1
    return res_graph




res_graph = dfs(graph)

res_graph.sort(key=lambda x: x.id)

for n in res_graph:
    print("{} {} {}".format(n.id, n.d, n.f))

Python: def dfs(v, cnt):
    D[v] = cnt
    cnt += 1
    for c in edge[v]:
        if D[c] == -1:
            cnt = dfs(c, cnt)
    F[v] = cnt
    cnt += 1
    return cnt


V = int(input())
edge = [[] for _ in range(V)]
for _ in range(V):
    u, _, *v = map(lambda x: int(x)-1, input().split())
    edge[u] = sorted(v)
D, F = [-1] * V, [-1] * V
_ = dfs(0, 1)
for i, (d, f) in enumerate(zip(D, F)):
    print(i, d, f)

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

d = [0] * n
f = [0] * n
isDiscovered = [False] * n
time_stamp = 0

def dfs(x):
    global time_stamp
    isDiscovered [x] = True
    time_stamp = time_stamp + 1
    d[x] = time_stamp
    for i in range(n):
        if a[x][i] == 1 and isDiscovered[i] == False:
            dfs(i)
    time_stamp = time_stamp + 1
    f[x] = time_stamp

for i in range(n):
    if isDiscovered[i] == False:
        dfs(i)

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

Python: from sys import stdin
input = stdin.readline

N = int(input())
WHITE = 0
GRAY = 1
BLACK = 2

M = [[0]*N for _ in range(N)]
color = [WHITE]*N  # colorの初期化は最初に行っておく。
d = [0]*N
f = [0]*N

def dfs_visit(u):
    global tt
    color[u] = GRAY
    tt += 1
    d[u] = tt # 最初の訪問
    for v in range(N):
        if M[u][v] == 0:
            continue
        if color[v] == WHITE:
            dfs_visit(v)
    color[u] = BLACK
    tt += 1
    f[u] = tt # 訪問の完了

def dfs():
    global tt
    tt = 0

    for u in range(N):
        if color[u] == WHITE:
            # 未訪問のuを始点として深さ優先探索
            dfs_visit(u)
    for u in range(N):
        print(str(u+1) + ' ' + str(d[u]) + ' ' + str(f[u]))
for _ in range(N):
    u, k, *vv = input().split()
    u = int(u)-1  # 0オリジンにする
    k = int(k)    # kは使わない
    for v in vv:
        v = int(v)-1
        M[u][v] = 1
dfs()

Python: global t
t = 0

class Node:
    def __init__(self, num, deg, neib):
        self.num = num
        self.deg = deg
        self.neib = neib

def dfs(G, d, f, now): #now:1,2,...
    #print("now:",now)
    global t
    t += 1
    #print("t:",t)
    if d[now-1] != 0:
        t -= 1
        #print("has searched or hit roop")
    else:
        d[now-1] = t
        #print("d:",d)
        #print("f:",f)
        for i in G[now-1].neib:
            #print("i:",i)
            if i != -1:
                #print("next node")
                dfs(G, d, f, i)
            #else: print("end of branch")
        t += 1
        f[now-1] = t

        #print("f:",f)


dnum = int(input()) #頂点数
N = []
for i in range(dnum):
    data = input().split()
    
    u = int(data[0])
    k = int(data[1])
    if k > 0:
        v = list(map(int, data[2:]))
    else:
        v = [-1]

    node = Node(u,k,v)
    N.append(node)

d = [0]*dnum #find time
f = [0]*dnum #finish time

while 0 in d:
    s = d.index(0)
    dfs(N, d, f, s+1)
    #print("looks like finish")

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

Python: class Node(object):
    def __init__(self, V):
        self.V = V
        self.find_time = 0
        self.finish_time = 0
        self.is_finded = False


n = int(input())
nodes = [0] * 100
for i in range(n):
    data = input().split()
    V = list(map(int, data[2:]))
    V.sort(reverse = True)
    nodes[int(data[0])] = Node(V)

find_q = []
find_q.append(1)
cnt = 1
q_size = len(find_q)
while q_size != 0:
    #print(find_q)
    node = nodes[find_q[q_size -1]]

    if node.is_finded == False:
        node.find_time = cnt
        cnt += 1
        node.is_finded = True
        if len(node.V) == 0:
            node.finish_time = cnt
            cnt += 1
            del find_q[q_size -1]
            q_size = len(find_q)
        else:
            for x in node.V:
                if x in find_q:
                    find_q.remove(x)
                if nodes[x].finish_time == 0: 
                    find_q.append(x)
            q_size = len(find_q)

    else:   #node is finded
        node.finish_time = cnt
        cnt += 1
        del find_q[q_size -1]
        q_size = len(find_q)
        continue

for i in range(1, n+1):
    print(i, nodes[i].find_time, nodes[i].finish_time)

Python: def d(u):
 global t
 C[u]=0;D[u]=t;t+=1
 for v in M[u]:
  v=int(v)-1
  if C[v]:d(v)
 F[u]=t;t+=1
N=int(input());R=range(N)
M=[input().split()[2:]for _ in R]
C,D,F=[1]*N,[0]*N,[0]*N
t=1
for i in R:
 if C[i]:d(i)
for i in R:print(i+1,D[i],F[i])