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 <bits/stdc++.h>
using namespace std;
#define _GLIBCXX_DEBUG
typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<pair<int, int>, int> PP;
// const ll INF = 1LL << 60;
const ll MOD = 1000000007;
const int INF = 1000000000;
const int MAX = 300000;

int GCD(int a, int b) { return b ? GCD(b, a % b) : a; }
//------------------------------------------------------------------------------------------------------------------------------
vector<vector<int>> G;
vector<int> d, f;
int t;
void dfs(int v) {
    d[v] = ++t;
    for(auto nv : G[v]){
        if(d[nv]>0){
            continue;
        }
        dfs(nv);
    }
    f[v] = ++t;
}

int main(void) { 
    int N;
    cin >> N;
    G.resize(N);
    d.resize(N);
    f.resize(N);
    for (int i = 0; i < N; i++) {
        int u, k;
        cin >> u >> k;
        u--;
        for(int i = 0; i < k; i++) {
            int v;
            cin >> v;
            v--;
            G[u].push_back(v);
        }
    }
    for(int i = 0; i < N; i++) {
        if(d[i]==0){
            dfs(i);
        }
    }
    for(int i = 0; i < N; i++) {
        cout << i + 1 << ' ' << d[i] << ' ' << f[i] << endl;
    }
}

C++: #include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <stack>

using namespace std;

int common_time=1,n;

int table[101][101],time_table[101][2];

void func(int node){
	if(time_table[node][0] == 0){
		time_table[node][0] = common_time++;
	}else{
		return;
	}
	for(int i=1;i<=n;i++){
		if(table[node][i] == 1){
			func(i);
		}
	}
	time_table[node][1] = common_time++;
}

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

	for(int i=1;i<=n;i++){
		for(int k=1;k<=n;k++){
			table[i][k]=0;
		}
		time_table[i][0]=0;
		time_table[i][1]=0;
	}

	for(int i=1;i<=n;i++){
		scanf("%d %d",&row,&num);
		for(int k=1;k<=num;k++){
			scanf("%d",&col);
			table[row][col]=1;
		}
	}

	for(int i=1;i<=n;i++){
		func(i);
	}

	for(int i=1;i<=n;i++){
		printf("%d %d %d\n",i,time_table[i][0],time_table[i][1]);
	}

    return 0;
}

C++: #include<iostream>

int main(){

  int n,a;
  std::cin>>n;

  int Adj[100][100],adj[100][100]={0},find[100][2],back[100],depth[100]={0},endflag[100]={0},flag;
  int u[n],k[n],kcou=0,timenow=0,v,pred,prev;
  for(int i=0;i<n;i++){
    std::cin>>u[i];
    std::cin>>k[i];
    for(int j=0;j<k[i];j++){
      std::cin>>Adj[i][j];
    }
  }
	
	/*
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
    	std::cout<<Adj[i][j]<<" ";
    }
  	std::cout<<"\n";
  }*/
	
	v=0;

	while(timenow<n*2){
		flag=0;
		//std::cout<<find[v][0]<<" "<<find[v][1];
		if(find[v][0]==NULL){
			timenow++;
			find[v][0]=timenow;
			flag=1;
			//std::cout<<flag<<" 1";
		}else if(find[v][1]==NULL){
			if(endflag[v]==1){
				timenow++;
				find[v][1]=timenow;
				flag=2;
			}
			//std::cout<<flag<<" 2";
		}else{
			v=back[v];
			flag=3;
			//std::cout<<flag<<" 0";
		}

		if(flag==0){
			pred=depth[v];
			depth[v]++;
			prev=v;
			v=Adj[v][pred]-1;
			back[v]=prev;
			//std::cout<<flag<<"\n";
		}else if(flag==1){
			if(endflag[v]==1){
				depth[v]++;
			}else{
				pred=depth[v];
				depth[v]++;
				prev=v;
				v=Adj[v][pred]-1;
				back[v]=prev;
				//std::cout<<v<<"\n";
			}
		}else if(flag==2){
			v=back[v];
			//std::cout<<flag<<"\n";
		}
		if(depth[v]>k[v]-1){
			endflag[v]=1;
		}
		
	}
	
	
	
	
  for(int i=0;i<n;i++){
     std::cout<<i+1<<" "<<find[i][0]<<" ";
     std::cout<<find[i][1]<<"\n";
    //std::cout<<"\n";
  }

  return 0;
}

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

const int SIZE = 100;
int Adj[SIZE][SIZE+3];
int d[SIZE];
int f[SIZE];
int t=0;

void DFS(int id){
    
    //t++;

    // タイムスタンプが押されている
    if (d[id-1] != 0){
        return;
    }

    d[id-1] = ++t;

    for(int i=2;Adj[id-1][i]!=0;i++){
        DFS(Adj[id-1][i]);
    }

    f[id-1] = ++t;
}

int main(){
    int n;
    cin >> n;
    
    // 初期化
    for(int i=0;i<SIZE;i++){
        d[i] = 0;
        f[i] = 0;
        for(int j=0;j<SIZE+3;j++){
            Adj[i][j] = 0;
        }
    }

    // 入力受付
    for(int i=0;i<n;i++){
        cin >> Adj[i][0] >> Adj[i][1];
        for(int j=0;j<Adj[i][1];j++){
            cin >> Adj[i][j+2];
        }
    }

    for(int i=1;i<=n;i++){
        if(d[i-1]!=0){
            continue;
        }
        DFS(i);
    }

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

C++: #include <bits/stdc++.h>
#define rep(i, n) for (int i=0; i<(n); ++i)
#define repr(i, a, b) for (int i=a; i<(b); ++i)
#define reprev(i, n) for (int i=n-1; i>=0; --i)
#define reprrev(i, a, b) for (int i=b-1; i>=(a); --i)
using namespace std;
using ll = long long;
using P = pair<int, int>;

vector<P> ans;
vector<vector<int>> e;

int dfs(int nn, int time) {
    // 探れるところがあるか探す
    if (ans[nn].first == 0) {
        // 到達していなければ時間を足して記録
        time += 1;
        ans[nn].first = time;
        // cout << "achived " << nn << ": " << time << endl; 
    }
    rep(i, e[nn].size()) {
        if (ans[e[nn][i]].first != 0) continue;
        // 到達していない箇所があれば入る
        time = dfs(e[nn][i], time);
    }
    time += 1;
    ans[nn].second = time;
    return time;
}

int main() {
    cout << fixed << setprecision(10);
    
    int n; cin >> n;
    // vector<vector<int>> e(n);
    e.resize(n);
    rep(i, n) {
        int id; cin >> id; id--;
        int k; cin >> k;
        rep(j, k) {
            int v; cin >> v; v--;
            e[id].emplace_back(v);
        }
    }

    // vector<P> ans(n);
    ans.resize(n);
    int time = 0;
    rep(i, n) {
        if (ans[i].first == 0) {
            time = dfs(i, time);
        }
    }
    rep(i, n) {
        cout << i+1 << " " << ans[i].first << " " << ans[i].second << endl;
    }
    return 0;
}