Go: package main

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

func main() {
	scn := bufio.NewScanner(os.Stdin)
	scn.Split(bufio.ScanWords)
	nextInt := func() int { scn.Scan(); r, _ := strconv.Atoi(scn.Text()); return r }
	w := bufio.NewWriter(os.Stdout)

	n := nextInt()
	vecs := make([][]int, n)
	for i := 0; i < n; i++ {
		u := nextInt()
		k := nextInt()
		for j := 0; j < k; j++ {
			vecs[u-1] = append(vecs[u-1], nextInt()-1)
		}
	}

	ds := make([]int, n)
	fs := make([]int, n)
	founds := make([]bool, n)
	t := 0
	for i := range founds {
		if !founds[i] {
			t = dfs(vecs, ds, fs, founds, i, t)
		}
	}

	for i := 0; i < n; i++ {
		fmt.Fprintln(w, i+1, ds[i], fs[i])
	}

	w.Flush()
}

func dfs(vecs [][]int, ds, fs []int, founds []bool, i, t int) (time int) {
	t++
	ds[i] = t
	founds[i] = true
	for _, v := range vecs[i] {
		if !founds[v] {
			t = dfs(vecs, ds, fs, founds, v, t)
		}
	}
	t++
	fs[i] = t

	return t
}

C++: #include <iostream>
#include <cstdio>
#include <vector>
#define N 100
typedef struct SearchTime SearchTime;

struct SearchTime{
    int find = -1;
    int comp = -1;
    bool flag = false;
    void print(){
        std::cout << find << " " << comp << '\n';
    }
};

int cnt = 1;
int A[N][N];
SearchTime st[N];

void input_graph(std::vector<std::vector<int> >& Adj, int n){
    int u, k, v;
    for(int i=0; i<n; i++){
        std::cin >> u >> k;
        for(int j=0; j<k; j++){
            std::cin >> v;
            Adj[u-1].push_back(v);
        }
    }
}

void input_A(std::vector<std::vector<int> >& Adj, int n){
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            A[i][j] = 0;
        }
    }
    for(int i=0; i<n; i++){
        int len = Adj[i].size();
        for(int j=0; j<len; j++){
            A[i][Adj[i][j]-1] = 1;
            A[Adj[i][j]-1][i] = -1;
        }
    }
}

void output_A(int n){
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            if(j+1==n)  printf("%3d\n", A[i][j]);
            else        printf("%3d", A[i][j]);
        }
    }
}

void result(int n){
    for(int i=0; i<n; i++){
        std::cout << i+1 << " ";
        st[i].print();
    }
}

void DFS(std::vector<std::vector<int> >& Adj, int n){
    int i = 0;
    int j;
    int nexti;              //毎回-1する.
    std::vector<int> tmp;   //軌跡を保存
    //深さ優先探索
    while(cnt <= n*2){
        //下層へ探索
        //std::cout << "\nstrat\n";
        while(i != -1){
            st[i].flag = true;
            st[i].find = cnt;
            cnt++;
            //std::cout << "cnt:" << cnt-1 << '\n';
            tmp.push_back(i);
            //std::cout << "tmp.size():" << tmp.size() << '\n';
            //std::cout << "i:" << i+1 << '\n';
            //次の葉を探す
            if((int)Adj[i].size() != 0){//葉が最深でないとき
                j = 0;
                nexti = Adj[i][j]-1;
                while(st[nexti].flag){
                    j++;
                    if(j == (int)Adj[i].size()){//もし葉がすべて探索済みなら
                        st[i].comp = cnt;
                        cnt++;
                        //std::cout << "tochu\n";
                        //std::cout << "cnt:" << cnt-1 << '\n';
                        i = -1; //2つ目のwhile文抜ける
                        break;
                    }
                    nexti = Adj[i][j]-1;
                }
                if(i != -1) i = nexti;
            }
            else{//葉が最深のとき
                st[i].comp = cnt;
                cnt++;
                i = -1; //2つ目のwhile文抜ける
                //std::cout << "saishin\n";
                //std::cout << "cnt:" << cnt-1 << '\n';
                //std::cout << "tmp.size():" << tmp.size() << '\n';
                //std::cout << "i:" << i << '\n';
            }
        }
        //ここから根に向かって戻る. 未探索の葉があればそちらへ行く
        //std::cout << "\nback\n";
        tmp.pop_back();
        i = (int)tmp.back();
        tmp.pop_back();
        //std::cout << "tmp.size():" << tmp.size() << '\n';
        //std::cout << "i:" << i+1 << '\n';
        j = 0;
        nexti = Adj[i][j]-1;
        while(st[nexti].flag){
            j++;
            if(j == (int)Adj[i].size()){//現在のノードから未探索の葉がない
                if((int)tmp.size() != 0){//まだtmpに軌跡が残っていれば
                    st[i].comp = cnt;
                    cnt++;
                    //std::cout << "cnt:" << cnt-1 << '\n';
                    i = (int)tmp.back();
                    tmp.pop_back();
                    //std::cout << "tmp.size():" << tmp.size() << '\n';
                    //std::cout << "i:" << i+1 << '\n';
                    j = 0;
                    nexti = Adj[i][j]-1;
                }
                else{//残っていないなら
                    st[i].comp = cnt;
                    cnt++;      //たぶんこれで終わる
                    //std::cout << "cnt:" << cnt-1 << '\n';
                    break;
                }
            }
            else{
                nexti = Adj[i][j]-1;
            }
        }
        tmp.push_back(i);
        i = nexti;
    }
}


int main(){
    int n;
    std::cin >> n;
    std::vector<std::vector<int> > Adj;
    Adj.resize(n);
    input_graph(Adj, n);
    //input_A(Adj, n);
    //output_A(n);
    DFS(Adj, n);
    result(n);
    return 0;
}

C++: #include <stdio.h>
#include <iostream>
#include <stack>
#include <string>
using namespace std;

#define NUM 100
int node_num;
int V[NUM + 1][NUM + 1];
int d[NUM + 1];
int f[NUM + 1];
string color[NUM + 1];
int t;
int pos;
stack<int> s;

void createAdj(int n){
    for(int i = 1; i < NUM; i++){
        for(int j = 1; j < NUM; j++){
            V[i][j] = 0;
        }
    }

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

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

        int num2;
        for(int j = 0; j < n; j++){
            scanf("%d", &num2);
            V[num1][num2] = 1;
        }
    }
}

int search(int n){
    for(int i = 1; i <= node_num; i++) {
        if(V[n][i] == 1 && color[i] == "white")
            return i;
    }
    return -1;
}

void dfs_init(){
    t = 0;
    for(int i = 0; i < NUM; i++){
        color[i] = "white";
    }
}

void dfs(){
    s.push(1);
    pos = 1;
    t++;
    color[1] = "grey";
    d[1] = t;

    while(s.size()){
        int u = s.top();
        int next_node = search(u);
        if(next_node != -1){
            pos = next_node;
            s.push(next_node);
            pos = next_node;
            t++;
            color[next_node] = "grey";
            d[next_node] = t;
        }else{
            s.pop();
            color[u] = "black";
            t++;
            f[u] = t;
        }
    }
}

void print(){
    for(int i = 1; i <= node_num; i++){
        printf("%d %d %d\n", i, d[i], f[i]);
    }
}

int main(void){
    scanf("%d", &node_num);
    createAdj(node_num);

    dfs_init();
    dfs();

    print();
}

C++: #include<iostream>
#define FOR(i,a,b) for (int i=(a);i<(b);i++)
using namespace std;
int G[100][100] = {};
int timer = 0;
typedef struct ANS
{
	int id, t, e;
	bool done;
};

void rec(ANS a[],int t)
{
	if (a[t].done == true)return;
	timer++;
	a[t].t = timer;
	a[t].done = true;
	FOR(i, 0, 100)
	{
		if (G[t][i] == 1)
		{
			rec(a, i);
		}
	}
	timer++;
	a[t].e = timer;
}

int main()
{
	ANS ans[101];
	int n;
	cin >> n;
	FOR(i, 0, n)
	{
		ans[i].id = i + 1;
		ans[i].done = false;
		int u, m;
		cin >> u >> m;
		FOR(j, 0, m)
		{
			int l;
			cin >> l;
			G[u - 1][l - 1] = 1;
		}
	}
	FOR(i, 0, n)
	{
		rec(ans, i);
	}
	FOR(i, 0, n)
	{
		cout << ans[i].id << " " << ans[i].t << " " << ans[i].e << endl;
	}
	return 0;
}