Go: package main

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

type TimeRecord struct {
	discoverTime int
	finishTime   int
}

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

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

	timeRecordMap := make([]TimeRecord, n)
	childrenMap := make([][]int, n)
	for i := 1; i <= n; i++ {
		node, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		timeRecordMap[node-1] = TimeRecord{-1, -1}

		childNum, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		childrenMap[node-1] = make([]int, childNum)
		for j := 0; j < childNum; j++ {
			child, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			childrenMap[node-1][j] = child
		}
	}

	timer := 1
	startNode := 1
	for {
		visit(startNode, &timer, childrenMap, timeRecordMap)
		startNode = findStartNode(childrenMap, timeRecordMap)
		if startNode < 0 {
			break
		}
	}
	for k, v := range timeRecordMap {
		fmt.Printf("%d %d %d\n", k+1, v.discoverTime, v.finishTime)
	}
}

func findStartNode(childrenMap [][]int, timeRecordMap []TimeRecord) int {
	x := -1
	for node, timeRecord := range timeRecordMap {
		if timeRecord.discoverTime < 0 {
			x = node + 1
			break
		}
	}
	return x
}

func visit(currentNode int, timer *int, childrenMap [][]int, timeRecordMap []TimeRecord) {
	if timeRecordMap[currentNode-1].discoverTime > 0 {
		return
	}
	children := childrenMap[currentNode-1]
	timeRecordMap[currentNode-1] = TimeRecord{*timer, timeRecordMap[currentNode-1].finishTime}
	(*timer)++
	for i := 0; i < len(children); i++ {
		visit(children[i], timer, childrenMap, timeRecordMap)
	}
	timeRecordMap[currentNode-1] = TimeRecord{timeRecordMap[currentNode-1].discoverTime, *timer}
	(*timer)++
}

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

C++: #include<iostream>
int main(){

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

  int Adj[100][100],adj[100][100]={0},find[100][2],back[100][100],depth[100]={0},endflag[100]={0},flag;
	int u[n],k[n],kcou=0,timenow=0,v,pred,prev,firstv,backcount[100]={0};
  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;
	firstv=0;
	while(timenow<n*2){
		flag=0;
		if(find[firstv][0]!=NULL&&find[firstv][1]!=NULL){
			for(int i=0;i<n;i++){
				if(find[i][0]==NULL){
					//std::cout<<i<<"\n";
					firstv=i;
					v=i;
					break;
				}
			}
		}
		
		//std::cout<<v+1<<" ";
		///std::cout<<find[v][0]<<" "<<find[v][1];
		
		if(find[v][0]==NULL){
			timenow++;
			find[v][0]=timenow;
			//std::cout<<" '"<<timenow<<"' ";
			flag=1;
			//std::cout<<flag<<" 1";
		}else if(find[v][1]==NULL){
			if(endflag[v]==1){
				if(backcount[v]<=1){
				timenow++;
				find[v][1]=timenow;
				//std::cout<<" '"<<timenow<<"' ";
				}
				flag=2;
			}
			//std::cout<<flag<<" 2";
		}else{
			backcount[v]--;
			v=back[v][backcount[v]];
			//backcount[v]--;
			flag=3;
			//std::cout<<flag<<" 0";
		}

		if(flag==0){
			pred=depth[v];
			depth[v]++;
			prev=v;
			v=Adj[v][pred]-1;
			back[v][backcount[v]]=prev;
			backcount[v]++;
			//std::cout<<flag<<"\n";
		}else if(flag==1){
			if(endflag[v]==0){
				if(Adj[v][depth[v]]-1!=v&&Adj[v][depth[v]]-1!=firstv){
					pred=depth[v];
					depth[v]++;
					prev=v;
					v=Adj[v][pred]-1;
					back[v][backcount[v]]=prev;
					backcount[v]++;
					//std::cout<<v<<"\n";
				}else{
					pred=depth[v];
					depth[v]++;
				}
			}
		}else if(flag==2){
			backcount[v]--;
			v=back[v][backcount[v]];
			//backcount[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<cstdio>
#include<array>
#include<vector>
#include<stack>
using namespace std;
const int MAX_V=101;
array<int,MAX_V> open{0};
array<int,MAX_V> close{0};
array<vector<int>,MAX_V> edge;
int t=0;

void dfs(int f){
  open[f]=++t;
  for(int a:edge[f]){
    if(open[a]==0){
      dfs(a);
    }
  }
  close[f]=++t;
}

int main(){
  int n;scanf("%d",&n);
  for(int i=0;i<n;i++){
    int u;scanf("%d",&u);
    int k;scanf("%d",&k);
    for(int j=0;j<k;j++){
      int v;scanf("%d",&v);
      edge[u].push_back(v);
    }
  }
  for(int i=0;i<n;i++)
    if(open[i+1]==0)
      dfs(i+1);
  for(int i=0;i<n;i++){
    printf("%d %d %d\n",i+1,open[i+1],close[i+1]);
  }
}

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

int A[101][101] = {0};
int n, tt = 0, d[101] = {0}, f[101] = {0}, color[101] = {0};
stack<int> S;

int next(int u) {
    int i;
    for ( i = 1; i <= n; i++ ) {
        if ( A[u][i] == 1 && color[i] != 1 ) return i;
    }

    return -1;
}

void dfs (int u) {
    int i, j ,k;
    S.push(u);
    d[u] = ++tt;
    color[u] = 1;
    while ( !S.empty() ) {
        j = S.top();
        i = next(j);
        if ( i != -1 ) {
            color[i] = 1;
            d[i] = ++tt;
            S.push( i );
        }
    else {
        f[j] = ++tt;
        S.pop();
    }
    }

}

int main() {
    int i, j, k, v;
    cin >> n;
    for ( i = 0; i < n; i++ ) {
        cin >> j >> k;
        while ( k-- ) {
            cin >> v;
            A[j][v] = 1;
        }
    }

    for ( i = 1; i <=n; i++ ) if ( color[i] != 1 ) dfs(i);
    for ( i = 1; i <=n; i++ ) cout << i << ' ' << d[i] << ' ' << f[i] << endl;

    return 0;

}

C++: #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cassert>
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REP(i,n) FOR(i,0,n)
#define rep(i,n) FOR(i,0,n)
#define DEBUG(x) cout<<#x<<": "<<x<<endl
#define vint vector<int>
#define vdouble vector<double>
#define vstring vector<string>
using namespace std;

#include<map>
#include<set>
#include<queue>

typedef long long ll;
typedef unsigned long long ull;

const int MAX_N = 1000000;
static const int INFTY = (1 << 21);

class Edge{
public:
    int from, to, cost;
    Edge(int from = 0, int to = 0, int cost = 0) :
            from(from), to(to), cost(cost){}

    bool operator < (const Edge &e) const{
        return cost < e.cost;
    }
    bool operator >(const Edge &e) const{
        return cost > e.cost;
    }

};

class Node{
public:
    vector<Edge> edges;
    int dist;
    int done;
    int times;
    int timee;

    Node(){
        dist = INFTY;
        done = 0;
    }
};

class Graph{
public:
    vector<Node> nodes;
    Graph(int n) {
        rep(i, n) { Node n;  nodes.push_back(n); }
    }
    Node& operator[](int i){
        return nodes[i];
    }
};

class Data{

public:
    int dist;
    Edge *edge;
    Data(int dist, Edge *edge) {
        this->dist = dist;
        this->edge = edge;
    }

    bool operator < (const Data &d) const{
        return dist < d.dist;
    }
    bool operator >(const Data &d) const{
        return dist > d.dist;
    }
};

Graph G(0);

int V;
int t;

void dfs(int v){
    if (G[v].done != 0) return;

    // fprintf(stderr, "%d %d\n", v, t);

    G[v].done = 1;
    t++;
    G[v].times = t;
    for(auto &e: G[v].edges){
        dfs(e.to);
    }
    t++;
    G[v].timee = t;
}

void dfs_run(){
    t = 0;
    dfs(0);
}

int main() {

    int V;
    cin >> V;
    G = Graph(V);

    rep(i, V){
        int from; cin >> from; from--;
        int e_count; cin >> e_count;

        vint vec;
        rep(j, e_count){
            int to; cin >> to; to--;
            vec.push_back(to);
        }
        sort(vec.begin(), vec.end());
        rep(j, e_count){
            G[from].edges.push_back(Edge(from, vec[j], 1));
        }
    }

    dfs_run();

    rep(i, V){
        fprintf(stdout, "%d %d %d\n", i+1, G[i].times, G[i].timee);
    }
}