Go: package main

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

// repr state of visited node
// WHITE yet visit
// GEAY  visiting
// BLACK visited
const (
	WHITE int = iota
	GRAY
	BLACK
)

type dfsGraph struct {
	g      [][]int
	colors []int
	stime  []int // Start time of visiting node
	ftime  []int // Finish time of visiting node
}

var time int

func makeAdjList() [][]int {
	var n int
	fmt.Scanf("%d", &n)

	adj := make([][]int, n)
	for i := 0; i < n; i++ {
		adj[i] = make([]int, n)
	}

	sc := bufio.NewScanner(os.Stdin)
	for i := 0; i < n; i++ {
		sc.Scan()
		nodeInfo := strings.Split(sc.Text(), " ")
		outDegree, _ := strconv.Atoi(nodeInfo[1])

		if outDegree > 0 {
			for k := 0; k < outDegree; k++ {
				j, _ := strconv.Atoi(nodeInfo[k+2])
				j-- // convert 1 based to 0 based
				adj[i][j] = 1
			}
		}
	}

	return adj
}

func (dg dfsGraph) dfsVisit(u int) {
	// 頂点uを訪問中に設定
	dg.colors[u] = GRAY
	time++
	dg.stime[u] = time

	// uの隣接nodeを訪問
	for v := 0; v < len(dg.g); v++ {
		if dg.g[u][v] == 0 {
			continue // 辺がなければスキップ
		}

		// vが未訪問なら訪問
		if dg.colors[v] == WHITE {
			dg.dfsVisit(v)
		}
	}

	// 頂点uを訪問済みに設定
	dg.colors[u] = BLACK
	time++
	dg.ftime[u] = time
}

func (dg dfsGraph) dfs() {
	for i := 0; i < len(dg.g); i++ {
		if dg.colors[i] == WHITE {
			dg.dfsVisit(i)
		}
	}
}

func (dg dfsGraph) printDfsTime() {
	for i := 0; i < len(dg.g); i++ {
		fmt.Printf("%d %d %d\n", i+1, dg.stime[i], dg.ftime[i])
	}
}

func main() {
	adj := makeAdjList()
	colors := make([]int, len(adj))
	stime := make([]int, len(adj))
	ftime := make([]int, len(adj))
	graph := dfsGraph{adj, colors, stime, ftime}
	graph.dfs()
	graph.printDfsTime()
}

C++: #include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<bitset>
#include<vector>
#include<deque>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<cmath>
#include<iomanip>
#include <functional>
using namespace std;
typedef long long ll;
const int mod = 1000000007;
const int INF = 1 << 28;
//cout << fixed << std::setprecision(9)
//memset(a, 0, sizeof(a));
//--------------------------

int n;
bool g[110][110];
int d[110];
int f[110];
int current;

void dfs1(int s)
{
	if (d[s] != -1) return;

	stack<int> stk;
	d[s] = ++current;
	stk.push(s);
	while (!stk.empty()) {
		int u = stk.top();
		int flag = 0;
		for (int j = 1; j <= n; j++) {
			if (g[u][j] && d[j] == -1) {
				flag = 1;
				stk.push(j);
				d[j] = ++current;
				break;
			}
		}

		if (flag == 0) {
			f[u] = ++current;
			stk.pop();
		}

	}
}

void dfs()
{
	for (int i = 1; i <= n; i++)
		dfs1(i);

}

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

	for (int i = 1; i <= n; i++) {
		d[i] = -1;
		f[i] = -1;
	}

	dfs();

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

	return 0;
}

C++: #include <cstdio>
#include <iostream>
#include <stack>
#define MAX_VERTEXES 100
#define ZERO 0
#define NIL -1

using namespace std;

//think easy make easy

int n;//num of vertexes(頂点)
int matrix_graph[MAX_VERTEXES+1+1][MAX_VERTEXES+1+1];//1オリジン

stack<int> stk;
bool discovered[MAX_VERTEXES+1+1];//1オリジン
int discovered_time[MAX_VERTEXES+1+1];
int completed_time[MAX_VERTEXES+1+1];
int current_time = 0;

void DFS(int v){
	int v_tmp;
	for(int i=1;i<=n;i++){
		//if(i == v);
		if(matrix_graph[v][i] == 1 && !discovered[i]){
			current_time++;
			discovered_time[i] = current_time;
			stk.push(v);
			matrix_graph[v][i] == 0;
			discovered[i] = true;
			DFS(i);
		}else if(matrix_graph[v][i] == 1 && discovered[i]){
			matrix_graph[v][i] == 0;
		}

		if(i == n){
			current_time++;
			completed_time[v] = current_time;
			//if(!stk.empty())
			//{
				//cout <<stk.top() <<endl;
				//v_tmp = stk.top();
				//stk.pop();
				//DFS(v_tmp);
			//}
		}
	}
}

int main(){
	scanf("%d",&n);

	int v_num;
	int k;//v_numの出次数

	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			matrix_graph[i][j] = ZERO;
		}
	}

	for(int i=0;i<n;i++){
		scanf("%d",&v_num);
		scanf("%d",&k);

		for(int j=0;j<k;j++){
			int v_num2;
			scanf("%d",&v_num2);
			matrix_graph[v_num][v_num2] = 1;
		}
	}

	for(int i=1;i<=n;i++){
		discovered[i] = false;
		discovered_time[i] = NIL;
		completed_time[i] = NIL;
	}

	for(int i=1;i<=n;i++){
	//	cout <<"c" <<current_time <<" ";
		//current_time++;//ここではなく
		if(!discovered[i]){
			current_time++;//ココ
			//cout <<i <<endl;
			discovered[i] = true;
			discovered_time[i] = current_time;
			DFS(i);
		}
	}

	for(int i=1;i<=n;i++){
		cout <<i <<" " <<discovered_time[i] <<" " <<completed_time[i] <<endl;
	}

	return 0;
}

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

enum Status {WHITE, GRAY, BLACK};

stack<int> stc;
Status *status;
int *discovered, *finished;
vector<vector<int>> a;
int n, timer;

void dfs(int i){
        if(status[i]==BLACK) return;
        if(status[i]==WHITE){
                discovered[i] = ++timer;
                status[i] = GRAY;
        }
        stc.push(i);

        for(int j=0;j<a[i].size();j++) dfs(a[i][j]);

        if(status[i]==GRAY){
                finished[i] = ++timer;
                status[i] = BLACK;
        }
        stc.pop();
}

int main(){

        cin>>n;
        a = vector<vector<int>>(n, vector<int>());
        status = new Status[n];
        discovered = new int[n];
        finished = new int[n];

        int m, k, r;
        for(int i=0;i<n;i++){
                cin>>r;
                cin>>m;
                for(int j=0;j<m;j++){
                        cin>>k;
                        a[r-1].emplace_back(k-1);
                }
        }
        for(int i=0;i<n;i++) status[i] = WHITE;

        timer = 0;
        dfs(0);


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

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

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

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


void dfs(){
  for(int u=0;u<n;u++) color[u] = WHITE;
  t = 0;

  for(int u=0;u<n;u++){
    if(color[u] == WHITE) visit(u);
  }

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

int main(){
  int u,v,k;

  cin >> n;
  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++){
    cin >> u >> k;
    u--;
    for(int j =0;j<k;j++){
      cin >> v;
      v--;
      M[u][v] = 1;
    }
  }

  dfs();
  
  return 0;
}

C++: #include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
#define INT(x) int x; scanf("%d",&x)
#define INPUT(x) scanf("%d",&x)
#define REP1(x,n) for(int x = 0; x < n; x++)
#define REP2(x,s,e) for(int x = s; x <= e; x++)
#define BR printf("\n")
#define INF 2000000000

vector<int> V[100];//0 origin
bool complete[100] = {};
stack<int> S;
int time_ = 1;
int NodeStump[100][2];//find,end

void DFS(){
    NodeStump[S.top()][0] = time_;
    time_++;//d++
    if (S.empty()) return;
    
    REP1(i,V[S.top()].size()){
        if (!complete[V[S.top()][i]]){
            S.push(V[S.top()][i]);
            DFS();
        }
    }
    
    complete[S.top()] = true;
    NodeStump[S.top()][1] = time_;
    S.pop();
    time_++;//d--
}

int main(){
    INT(N);
    
    REP1(i,N){
        int from,n;
        scanf("%d %d",&from,&n);
        REP1(j,n){
            INT(to);
            V[i].push_back(to - 1);
        }
    }
    
    S.push(0);
    
    DFS();
    
    REP1(i,N){
        printf("%d %d %d\n",i+1,NodeStump[i][0],NodeStump[i][1]);
    }
    
    return 0;
}