Go: package main

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

const (
	initialBufSize = 100000
	maxBufSize     = 1000000
)

var sc *bufio.Scanner

func initScanner(r io.Reader) *bufio.Scanner {
	buf := make([]byte, initialBufSize)

	sc := bufio.NewScanner(r)
	sc.Buffer(buf, maxBufSize)
	sc.Split(bufio.ScanWords) // bufio.ScanLines
	return sc
}

func main() {
	sc = initScanner(os.Stdin)
	resolve(parseProblem())
}

type graph struct {
	size  int
	edges [][]int
}

func parseProblem() *graph {
	n := scanInt(sc)
	g := &graph{
		size:  n,
		edges: make([][]int, n),
	}
	for i := 0; i < g.size; i++ {
		_ = scanInt(sc)
		k := scanInt(sc)
		g.edges[i] = make([]int, k)
		for j := 0; j < k; j++ {
			g.edges[i][j] = scanInt(sc) - 1
		}
	}
	return g
}

func resolve(g *graph) {
	ds := make([]int, g.size)
	fs := make([]int, g.size)
	time := 0
	for i := 0; i < len(ds); i++ {
		if ds[i] == 0 {
			time++
			time = _dfs(ds, fs, time, g, i)
		}
	}
	for i := 0; i < len(ds); i++ {
		fmt.Println(i+1, ds[i], fs[i])
	}
	return
}

func _dfs(ds, fs []int, time int, g *graph, idx int) int {
	ds[idx] = time
	for _, next := range g.edges[idx] {
		if ds[next] > 0 {
			continue
		}
		time++
		time = _dfs(ds, fs, time, g, next)
	}
	time++
	fs[idx] = time
	return time
}

// snip-scan-funcs
func scanInt(sc *bufio.Scanner) int {
	sc.Scan()
	i, _ := strconv.Atoi(sc.Text())
	return int(i)
}
func scanString(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

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;
}