Go: package main

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

type vertexId int

type vertex struct {
	id vertexId
	firstVisitAt int
	finishVisitAt int
	adjs []vertexId
}

func createVertex(id int, adjsInt []int) vertex {
	adjs := make([]vertexId, len(adjsInt))
	for i := 0; i < len(adjs); i++ {
		adjs[i] = vertexId(adjsInt[i])
	}
	return vertex{
		id: vertexId(id),
		firstVisitAt: 0,
		finishVisitAt: 0,
		adjs: adjs,
	}
}

func (v *vertex) doesAllAdjsVisited(vertices []vertex) bool {
	for _, vId := range v.adjs {
		adj := vertices[vId-1]
		if !adj.isVisited() {
			return false
		}
	}
	return true
}

func (v *vertex) isFirstVisit() bool {
	return v.firstVisitAt == 0
}

func (v *vertex) isVisited() bool {
	return v.firstVisitAt > 0
}

func (v *vertex) nextVertex(vertices []vertex) (vertexId, error) {
	for _, vId := range v.adjs {
		adj := vertices[vId-1]
		if !adj.isVisited() {
			return vId, nil
		}
	}
	return vertexId(-1), fmt.Errorf("illegal")
}

func dfs(currentId vertexId, timestamp int, vertices []vertex) int {
	timestamp = timestamp + 1
	currentVertex := &vertices[currentId-1]
	if currentVertex.isFirstVisit() {
		currentVertex.firstVisitAt = timestamp
	}
	for !currentVertex.doesAllAdjsVisited(vertices) {
		nextVertexId, _ := currentVertex.nextVertex(vertices)
		timestamp = dfs(nextVertexId, timestamp, vertices)
	}
	timestamp = timestamp + 1
	currentVertex.finishVisitAt = timestamp
	return timestamp
}

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	n, err := nextInt(sc)
	if err != nil {
		panic(err)
	}

	vertices := make([]vertex, n)
	for i := 0; i < n; i++ {
		id, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjN, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjs := make([]int, adjN)
		for j := 0; j < adjN; j++ {
			adjId, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			adjs[j] = adjId
		}
		vertices[i] = createVertex(id, adjs)
	}

	dfs(vertexId(1), 0, vertices)

	for i := 0; i < n; i++ {
		fmt.Printf("%d %d %d\n", vertices[i].id, vertices[i].firstVisitAt, vertices[i].finishVisitAt)
	}
}

func nextText(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

func nextInt(sc *bufio.Scanner) (int, error) {
	return strconv.Atoi(nextText(sc))
}

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

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

std::vector<std::vector<int>> edges;
std::vector<int> d, f;

// dfs(x, t) := 頂点 x に時刻 t で初めて訪れたときに d, f を更新して戻ってきたときのタイムスタンプを返す
int dfs(int x, int t) {
	d[x] = t;

	for (int i = 0; i < edges[x].size(); ++i) {
		int dist = edges[x][i];
		if (d[dist] == -1)
			t = dfs(dist, t + 1);
	}

	f[x] = t + 1;
	return f[x];
}

int main() {
	int n;
	std::cin >> n;

	edges.resize(n);
	d.resize(n, -1);
	f.resize(n);

	for (int i = 0; i < n; ++i) {
		int u, k;
		std::cin >> u >> k;
		--u;

		for (int j = 0; j < k; ++j) {
			int v;
			std::cin >> v;
			--v;

			edges[u].push_back(v);
		}
	}

	int t = 0;
	for (int i = 0; i < n; ++i)
		if (d[i] == -1)
			t = dfs(i, t + 1);

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

C++: #include <bits/stdc++.h>
#define FOR(i, a, b) for(int i = (a); i < (b); ++i)
#define REP(i, n) for(int i = 0; i < (n); ++i)
#define SORT(v) sort(v.begin(), v.end());
#define pb(a) push_back(a)
using ll = long long;
using namespace std;

#define WHITE 1
#define GRAY 2
#define BLACK 3

int now, n, u, k, v, tree[102][102], timeTable[102][2], color[102], timeNow = 1;
stack<int> st;

void dfs(){
    while(1){
        if(st.empty()){
            FOR(l, 1, n + 1){
                cout << l << " " << timeTable[l][0] << " " << timeTable[l][1] << endl;
            }
            break;
        }else{
            now = st.top();
          	cout << now << " " << timeNow << endl;
          	if(color[now] == WHITE){
            	timeTable[now][0] = timeNow;
            }
            color[now] = GRAY;
            int cnt = 1;
            while(1){
                if(cnt == n + 1){
                    st.pop();
                    color[now] = BLACK;
                    timeTable[now][1] = timeNow + 1;
                    break;
                }else if(tree[now][cnt] && color[cnt] == WHITE){
                    st.push(cnt);
                    break;
                }
                cnt++;
            }
            timeNow++;
        }
    }
}

int main(){
    cin >> n;
  	REP(i, 102){
    	REP(j, 102){
        	tree[i][j] = 0;
        }
    }
    REP(i, n){
        cin >> u >> k;
        color[i + 1] = WHITE;
        REP(j, k){
            cin >> v;
            tree[u][v] = 1;
        }
    }
    st.push(1);
    dfs();
}