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) isVisited() bool {
	return v.firstVisitAt > 0
}

func dfs(currentId vertexId, timestamp int, vertices []vertex) int {
	currentVertex := &vertices[currentId-1]
	if currentVertex.isVisited() {
		return timestamp
	}
	timestamp = timestamp + 1
	currentVertex.firstVisitAt = timestamp
	for _, adjId := range currentVertex.adjs {
		timestamp = dfs(adjId, timestamp, vertices)
	}
	timestamp = timestamp + 1
	currentVertex.finishVisitAt = timestamp
	return timestamp
}

func solveDfs(vertices []vertex) {
	timestamp := 0
	for {
		vid := vertexId(-1)
		for i := 0; i < len(vertices); i++ {
			if !vertices[i].isVisited() {
				vid = vertexId(i+1)
				break
			}
		}
		if vid > 0 {
			timestamp = dfs(vid, timestamp, vertices)
		} else {
			break
		}
	}
}

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

	solveDfs(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<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();
}

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

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

	stack<int> stk;
	d[s] = 0;
	stk.push(s);
	int current = 0;
	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]+1 << " " << f[i]+1 << endl;
	}

	return 0;
}

C++: #define _USE_MATH_DEFINES

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <list>

long long int INF = 1e18;
using namespace std;

typedef pair<long long int, long long int> P;

long long int DP[1001][1001] = {};

int n;
int s[200], t[200];
bool visited[200] = {};

int dfs(int u, int d){
	if(visited[u]){
		return d - 1;
	}
	visited[u] = true;
	s[u] = d;
	for(int i = 0; i < n; i++){
		if(DP[u][i]){
			d = dfs(i, d + 1);
		}
	}
	t[u] = d + 1;
	return d + 1;
}

int main(){
	
	cin >> n;
	
	for(int loop = 0; loop < n; loop++){
		
		int id, k;
		cin >> id >> k;
		id--;
		
		for(int i = 0; i < k; i++){
			int num;
			cin >> num;
			num--;
			DP[id][num] = 1;
		}
		
	}
	
	dfs(0, 1);
	
	for(int i = 0; i < n; i++){
		cout << i + 1 << " " << s[i] << " " << t[i] << endl;
	}
	
	return 0;
}