Go: package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

const N = 100

const (
	WHITE = iota
	GRAY
	BLACK
)

type Graph struct {
	M               [N][N]int
	color, d, f, nt [N]int
	tt              int
}

func (g *Graph) next(u, n int) int {
	for v := g.nt[u]; v < n; v++ {
		g.nt[u] = v + 1
		if g.M[u][v] != 0 {
			return v
		}
	}
	return -1
}

func (g *Graph) dfsVisit(r, n int) {
	var S []int
	S = append([]int{r}, S...)
	g.color[r] = GRAY
	g.tt++
	g.d[r] = g.tt

	for len(S) != 0 {
		u := S[0]
		v := g.next(u, n)
		if v == -1 {
			S = S[1:]
			g.color[u] = BLACK
			g.tt++
			g.f[u] = g.tt
			continue
		}

		if g.color[v] != WHITE {
			continue
		}

		g.color[v] = GRAY
		g.tt++
		g.d[v] = g.tt
		S = append([]int{v}, S...)
	}
}

func (g *Graph) dfs(n int) string {
	for i := 0; i < n; i++ {
		g.color[i] = WHITE
	}
	g.tt = 0

	for u := 0; u < n; u++ {
		if g.color[u] == WHITE {
			g.dfsVisit(u, n)
		}
	}

	var out bytes.Buffer
	for i := 0; i < n; i++ {
		out.WriteString(fmt.Sprintf("%d %d %d\n", i+1, g.d[i], g.f[i]))
	}

	return strings.TrimRight(out.String(), "\n")
}

func answer(reader io.Reader) string {
	sc := bufio.NewScanner(reader)
	sc.Split(bufio.ScanWords)

	sc.Scan()
	n, _ := strconv.Atoi(sc.Text())

	var g Graph
	for i := 0; i < n; i++ {
		sc.Scan()
		u, _ := strconv.Atoi(sc.Text())
		sc.Scan()
		k, _ := strconv.Atoi(sc.Text())
		u--
		for j := 0; j < k; j++ {
			sc.Scan()
			v, _ := strconv.Atoi(sc.Text())
			v--
			g.M[u][v] = 1
		}
	}

	return g.dfs(n)
}

func main() {
	fmt.Println(answer(os.Stdin))
}

C++: #include <iostream>
#include <vector>

using namespace std;

struct Edge
{
	int to;
};

vector<vector<int>> DFS(vector<vector<Edge>>& G)
{
	int timecounter = 0;
	vector<vector<int>> result;
	result = vector<vector<int>>(2, vector<int>(G.size(), 0));
	vector<int> prev(G.size(),0);
	
	for(int i = 0; i < G.size(); i++){
		int next = i + 1;
		while(result[1][i] == 0){
			int tmp;
			if(result[0][next - 1] == 0){
				timecounter += 1;	
				result[0][next - 1] = timecounter;
			}

			if(G[next - 1].empty()){
				if(result[1][next - 1] == 0){
					timecounter += 1;
					result[1][next - 1] = timecounter;
				}
				next = prev[next - 1];
			}else{
				tmp = G[next - 1].begin()->to;
				G[next - 1].erase(G[next - 1].begin());
				prev[tmp - 1] = next;
				next = tmp;
			}
		}
	}
	return result;
}

int main(void)
{
	int n;
	cin >> n;

	vector<vector<Edge>> AdjList(n);
	for(int i = 0; i < n; i++){
		int u, k;
		cin >> u >> k;
		for(int j = 0; j < k; j++){
			int v;
			cin >> v;
			AdjList[i].push_back(Edge{v});
		}
	}

	vector<vector<int>> timestump = DFS(AdjList);
	
	for(int i = 0; i < AdjList.size(); i++){
		cout << i + 1 << " " << timestump[0][i] << " " << timestump[1][i] << endl;
	}
	return 0;
}

C++: #include <iostream>
#include <stack>
#define MAX 100
using namespace std;

enum Color {
  WHITE, GRAY, BLACK
};

int G[MAX][MAX];
int n;
int d[MAX];
int f[MAX];
Color color[MAX];
int cur_time;


void dfs_init() {
  for (int i = 0; i < n; i++) {
    color[i] = WHITE;
  }
  cur_time = 0;
}

void dfs_main(int v) {
  if (color[v] == BLACK) return;
  color[v] = GRAY;
  d[v] = ++cur_time;
  for (int i = 0; i < n; i++) {
    if (G[v][i] && color[i] == WHITE) {
      dfs_main(i);
    }
  }
  color[v] = BLACK;
  f[v] = ++cur_time;
}

void dfs() {
  dfs_init();
  for (int i = 0; i < n; i++) {
    dfs_main(i);
  }
}


int main() {
  cin >> n;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      G[i][j] = 0;
    }
  }
  for (int i = 0; i < n; i++) {
    int vi, out_v_num;
    cin >> vi;
    cin >> out_v_num;
    for (int j = 0; j < out_v_num; j++) {
      int out_vi;
      cin >> out_vi;
      G[vi-1][out_vi-1] = 1;
    }
  }

  dfs();

  for (int i = 0; i < n; i++) {
    cout << i+1 << " " << d[i] << " " << f[i] << endl;
  }
  return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;
#define repd(i,a,b) for (int i=(a);i<(b);i++)
#define rep(i,n) repd(i,0,n)
#define all(x) (x).begin(),(x).end()
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
typedef long long ll;
const long long INF = 1LL << 60;
typedef pair<int, int> P;

int dis;
vector<vector<int>> G(101);
bool visited[101];
int d[101];
int f[101];

void dfs(int v) {
    if (visited[v]) return;
    visited[v] = true;
    d[v] = dis + 1;
    dis++;
    rep(i, G[v].size()) {
        dfs(G[v][i]);
    }
    f[v] = dis + 1;
    dis++;
}

int main()
{
    int N;
    cin >> N;

    rep(i, N) {
        int u, k;
        cin >> u >> k;
        rep(j, k) {
            int v;
            cin >> v;
            G[u - 1].push_back(v - 1);
        }
    }

    rep(i, N) {
        if (!visited[i]) dfs(i);
    }

    rep(i, N) {
        cout << i + 1 << " " << d[i] << " " << f[i] << endl;
    }
    return 0;
}

C++: #include<iostream>
#define N 100
#define WHITE 0
#define GRAY 1
#define BLACK 2

int n,M[N][N];
int color[N],d[N],f[N],tt;

void dfs_visit(int u){
    int v;
    color[u]=GRAY;
    d[u]=++tt;
 
    for(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(){
    int u;
 
    for(u=0; u<n; u++){
        color[u]=WHITE;
    }
    tt=0;
    for(u=0; u<n; u++){
        if(color[u]==WHITE){dfs_visit(u);}
    }
    for(u=0; u<n; u++){
        printf("%d %d %d\n",u+1,d[u],f[u]);
    }
}

int main(){
    int i,j,k,u,v;
    scanf("%d",&n);
    for(i=0; i<n; i++){
        for(j=0; j<n; j++){
            M[i][j]=0;
        }
    }

    for(i=0; i<n; i++){
        scanf("%d %d",&u,&k);
        u--;
        for(j=0; j<k; j++){
            scanf("%d",&v);
            v--;
            M[u][v]=1;
        }
    }

    dfs();
    return 0;
}

C++: // Ref : https://book.mynavi.jp/ec/products/detail/id=35408

#include <iostream>
using namespace std;

static const int N = 100;
int G[N][N] = { {} };
int n, t = 0;
int detected_t[N] = {};
int finished_t[N] = {}; 

void depthFirstSearch(int ix) {
	if (!detected_t[ix - 1]) {
		detected_t[ix - 1] = ++t;
		for (int j = 0; G[ix - 1][j]; j++) {
			depthFirstSearch(G[ix - 1][j]);
		}
		if (!finished_t[ix - 1]) finished_t[ix - 1] = ++t;
	}
}

void myCheck() {
	for (int i = 0; i < n; i++) {
		cout << "index " << i + 1 << " : ";
		for (int j = 0; G[i][j]; j++) {
		if (j) cout << " ";
		cout << G[i][j];
		}
		cout << " time " << detected_t[i] << ", " << finished_t[i] << endl;
	}
}

int main() {
	int ix, deg;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> ix >> deg;
		for (int j = 0; j < deg; j++) cin >> G[ix - 1][j];
	}

	depthFirstSearch(1);
	//myCheck();

	for (int i = 0; i < n; i++) cout << i + 1 << " " << detected_t[i] << " " << finished_t[i] << endl;

	return 0;
}

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

vector<vector<int>> G;
vector<int> used;
vector<int> found;
vector<int> done;

int dfs(int v, int t){
    if(!used[v]){
        used[v] = 1;
        found[v] = t;
    }
    for(long long i=0; i<G[v].size(); i++){
        int nv = G[v][i];
        if(used[nv]) continue;
        else{
            t = dfs(nv, ++t);
        }
    }
    return done[v] = ++t;
}

int main(){
    int N; cin>>N;
    G.resize(N);
    used.resize(N, 0);
    found.resize(N, 0);
    done.resize(N, 0);
    found[0] = 1;
    for(long long i=0; i<N; i++){
        int u, k; cin >> u >>k;
        u--;
        G[u].resize(k);
        for(long long j=0; j<k; j++){
            int v; cin >> v;
            v--;
            G[u][j] = v;
        }
    }
    dfs(0, 1);
    for(long long i=0; i<N; i++){
        cout << i+1 << " " << found[i] << " " << done[i] << endl;
    }
    return 0;
}