Go: package main

import (
	"fmt"
)

func main() {
	var n int
	fmt.Scan(&n)
	g := make([][]int, n+1)
	for i := 0; i < n; i++ {
		var u,k int
		fmt.Scan(&u)
		fmt.Scan(&k)
		g[u] = make([]int, k)
		for j := 0; j < k; j++ {
			fmt.Scan(&g[u][j])
		}
	}

	d := make([]int, n+1)
	f := make([]int, n+1)
	dfs(&g, &d, &f, 1, 1)

	for i := 1; i <= n; i++ {
		fmt.Printf("%d %d %d\n", i, d[i], f[i])
	}
}

func dfs(g *[][]int, d *[]int, f *[]int, id int, t int) int {
	if (*d)[id] > 0 {
		return t
	}
	(*d)[id] = t
	t += 1
	for i := 0; i < len((*g)[id]); i++ {
		t = dfs(g, d, f, (*g)[id][i], t)
	}
	(*f)[id] = t
	return t+1
}

C++: #include <cassert>
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <complex>

#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#define rep(i,n) for(int i=0;i<(n); i++)
#define rep2(i,n) for(int i=1;i<=(n);i++)
#define WHITE 0
#define GRAY 1
#define BLACK 2

using namespace std;
typedef long long ll;
const int NMAX = 100;
const int k = 200000;
static const int INF = 1<<29;
string s,t,ans;
int dp[3001][3001];
ll gcd(ll a, ll b){
if(a<b) swap(a,b);
    if(b==0) return a;
    return gcd(b, a%b);
}
int n,M[NMAX+1][NMAX+1]={0};
int color[NMAX]={WHITE},d[NMAX],f[NMAX],tt;

void dfs_visit(int u){
    color[u]=GRAY;
    d[u] = ++tt; //最初の訪問
    rep2(v,n){
        if(M[u][v]==0) continue;
        if(color[v]==WHITE){
            dfs_visit(v); //再帰
        }
    }
    color[u]=BLACK;
    f[u] = ++tt; //訪問完了
}

void dfs(){
    //初期化はcolor[NMAX]の定義で完了
    tt=0; //時間メモ
    rep2(u,n){
        if(color[u]==WHITE){
            dfs_visit(u); //まだ未踏の地であったらdfs_visit関数を動かす。
        }
    }
    rep2(u,n){
        cout << u << " " << d[u] << " " << f[u] << endl;
    }
}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(0); //この2行はより速度を向上させる
    // 追加２, 以降 cin の入力元が 'input.txt' になる


    int u,v,k;
    cin >> n;
    rep2(i,n){
        int u,k;
        cin >> u >> k;
        int v[k+1];
        rep2(j,k) cin >> v[j];
        rep2(j,k){
            M[i][v[j]]=1;
        }
    }
    dfs();
    return 0;
}

C++: #include <cstdio>
#include <cstring>
#include <stack>
#define N 110
using namespace std;
stack<int> s;
int n;
int m[N][N];
int used[N];
int time = 1;
int bb_start[N];
int bb_end[N];
int getnext(int u){
    for(int i = 1; i <= n; i++){
        if(m[u][i] == 1 && used[i] == 0) return i;
    }
    return -1;
}
void dfs(int root){
    used[root] = 1;
    bb_start[root] = time++;

    while(!s.empty()) s.pop();
    s.push(root);
    while(!s.empty()){
        int u = s.top();
        int v = getnext(u);
        if(v != -1 && used[v] == 0){
            used[v] = 1;
            bb_start[v] = time++;
            s.push(v);
        } else{
            bb_end[u] = time++;
            s.pop();
        }
    }
}
int main(){
    for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) m[i][j] = 0;
    for(int i = 0; i < N; i++) used[i] = 0;
    scanf("%d", &n);
    for(int p = 0; p < n; p++){
        int node, k;
        scanf("%d %d", &node, &k);
        for(int i = 0; i < k; i++){
            int b;
            scanf("%d", &b);
            m[node][b] = 1;
        }
    }
    for(int i = 1; i <= n; i++) if(used[i] == 0) dfs(i);
    for(int i = 1; i <= n; i++){
        printf("%d %d %d\n", i, bb_start[i], bb_end[i]);
    }
    return 0;
}

C++: def dfs(n):
    global t
    S[n] = t
    DP[n]=1
    for i in A[n][2:]:
        if not DP[i]:
            t += 1
            dfs(i)
    t += 1
    F[n] = t
n = int(input())
A = [0]*(n+1)
S = [0]*(n+1)
F = [0]*(n+1)
DP = [0]*(n+1)
for i in range(n):
    A[i+1] = [int(i) for i in input().split()]
t = 0
for i in range(1,n+1):
    if not DP[i]:
        t+=1
        dfs(i)
for i in range(1,n+1):
    tmp = "{} {} {}".format(i,S[i],F[i])
    print(tmp)

C++: #include<iostream>
using namespace std;

#define N 100
#define WHITE 0
#define GRAY 1
#define BLACK 2

int time_stamp;
int M[N+1][N+1];

void dfs(int n, int vertex, int d[], int f[], int color[]) {  
  color[vertex] = GRAY;
  d[vertex] = ++time_stamp;
  for (int i = 1; i <= n; i++) {    
    if (M[vertex][i] && color[i] == WHITE) {
      dfs(n, i, d, f, color);
    }
  }
  color[vertex] = BLACK;
  f[vertex] = ++time_stamp;
}

void search(int n, int d[], int f[], int color[]) {
  // 初期状態
  for (int i = 1; i <= n; i++) color[i] = WHITE;
  time_stamp = 0;
  // dfs
  for (int i = 1; i <= n; i++) {
    if (color[i] == WHITE) {
      dfs(n, i, d, f, color);
    }
  }
}

int main() {
  int i, j, n, u, k, v, d[N+1], f[N+1], color[N+1];
  
  cin >> n;
  // 隣接行列を取得
  for (i = 1; i <= n; i++) {
    for (j = 1; j <= n; j++) {
      M[i][j] = 0;
    }
  }
  for (i = 0; i < n; i++) {
    cin >> u >> k;
    for (j = 0; j < k; j++) {
      cin >> v;
      M[u][v] = 1;
    }
  }

  search(n, d, f, color);

  for (i = 1; i <= n; i++) cout << i << " " << d[i] << " " << f[i] << endl;    

  return 0;
}

C++: #include <cstdio>

typedef struct Node {
    int id;
    int d;
    int f;
    int count;
} Node;


int count(int id, int now, Node *node, int a[101][100]){
    if(node[id].d == 0) node[id].d = now;
    if(node[id].f != 0) return now - 1;
    if(node[id].count == 0){
        node[id].f = now + 1;
        return node[id].f;
    }
    for(int i = 0; i < node[id].count; ++i){
        int nextId = a[id][i];
        now = count(nextId, now + 1, node, a);
    }
    node[id].f = now + 1;
    return node[id].f;
}

int main(){
    int n;
    std::scanf("%d", &n);
    Node node[101];
    int a[101][100];
    for(int i = 1; i <= n; ++i){
        int id;
        std::scanf("%d", &id);
        node[id].id = id;
        std::scanf("%d", &node[id].count);
        for(int j = 0; j < node[id].count; ++j){
            std::scanf("%d", &a[i][j]);
        }
    }
    count(1, 1, node, a);
    for(int i = 1; i <= n; ++i){
        std::printf("%d %d %d\n", node[i].id, node[i].d, node[i].f);
    }

    return 0;
}

C++: #include<iostream>
using namespace std;

int time1 = 0;
int a[110][110] = {};
int d[110] = {};
int f[110] = {};
int n;
int p;

void dfs(int cur){
  if(d[cur]==0){
    d[cur] = time1;
  }
  time1 += 1;
  f[cur] = time1;

  for(int dst=1;dst<=n;dst++){
    if(a[cur][dst]==1&&d[dst]==0){
      a[cur][dst]=2;
      dfs(dst);
    }
  }
  for(int k=1;k<=n;k++){
    if(a[k][cur]==2){
      a[k][cur]=1;
      p+=1;
      dfs(k);
    }else{
      p=0;
    }
  }
  if(p==0){
    for(int k=1;k<=n;k++){
      if(d[k]==0){
	time1+=1;
	dfs(k);
      }
    }
  }
}

int main(){
  cin>>n;
  for(int i=1;i<=n;i++){
    int u,k;
    cin>>u>>k;
    for(int j=0;j<k;j++){
      int v;
      cin>>v;
      a[i][v]=1;
    }
  }
  time1 += 1;
  dfs(1);
  for(int k=1;k<=n;k++){
    cout<<k<<" "<<d[k]<<" "<<f[k]<<endl;
  }
}