Go: package main

import "fmt"

type node struct {
	id, d, v int
	adj      []node
}

var n int
var seen []bool
var graph []node

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func dfs(v, t int) int {
	// fmt.Printf("dfs(v %d, t %d) en:\n", v, t)
	seen[v] = true
	graph[v].v = t
	tt := t
	for _, vv := range graph[v].adj {
		if !seen[vv.id] {
			tt = max(tt, dfs(vv.id, tt+1))
		}
	}
	graph[v].d = tt + 1
	// fmt.Printf("dfs(v %d, t %d) ex: d %d\n", v, t, graph[v].d)
	return graph[v].d
}

func main() {
	fmt.Scan(&n)
	graph = make([]node, n+1)
	for i := 1; i <= n; i++ {
		var u, k, v int
		fmt.Scan(&u, &k)
		graph[u].id = u
		// 頂点uはk個の隣接頂点を持っている
		for j := 0; j < k; j++ {
			fmt.Scan(&v)
			var t node
			t.id = v
			graph[u].adj = append(graph[u].adj, t)
		}
	}
	// fmt.Println("n", n, "graph", graph)
	seen = make([]bool, n+1)
	// t := dfs(1, 1)
	v, t := 1, 1
	done := false
	for !done {
		tt := dfs(v, t)
		done = true
		for i := range seen {
			if !seen[i] {
				done = false
				v = graph[i].id
				t = tt
				break
			}
		}
	}
	for i := 1; i <= n; i++ {
		fmt.Printf("%d %d %d\n", i, graph[i].v, graph[i].d)
	}
}

C++: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;

#define REP(i,n) for(long long i = 0; i < (n); i++)
#define FOR(i, m, n) for(long long i = (m);i < (n); ++i)
#define ALL(obj) (obj).begin(),(obj).end()
#define SPEED cin.tie(0);ios::sync_with_stdio(false);

template<class T> using V = vector<T>;
template<class T, class U> using P = pair<T, U>;
template<class T> using PQ = priority_queue<T>;
template<class T> using PQR = priority_queue<T,vector<T>,greater<T>>;

constexpr long long MOD = (long long)1e9 + 7;
constexpr long long MOD2 = 998244353;
constexpr long long HIGHINF = (long long)1e18;
constexpr long long LOWINF = (long long)1e15;
constexpr long double PI = 3.1415926535897932384626433;

template <class T> vector<T> make_v(size_t N,T init){return vector<T>(N,init);}
template <class... T> auto make_v(size_t N,T... t){return vector<decltype(make_v(t...))>(N,make_v(t...));}
template <class T> void corner(bool flg, T hoge) {if (flg) {cout << hoge << endl; exit(0);}}
template <class T, class U>ostream &operator<<(ostream &o, const map<T, U>&obj) {o << "{"; for (auto &x : obj) o << " {" << x.first << " : " << x.second << "}" << ","; o << " }"; return o;}
template <class T>ostream &operator<<(ostream &o, const set<T>&obj) {o << "{"; for (auto itr = obj.begin(); itr != obj.end(); ++itr) o << (itr != obj.begin() ? ", " : "") << *itr; o << "}"; return o;}
template <class T>ostream &operator<<(ostream &o, const multiset<T>&obj) {o << "{"; for (auto itr = obj.begin(); itr != obj.end(); ++itr) o << (itr != obj.begin() ? ", " : "") << *itr; o << "}"; return o;}
template <class T>ostream &operator<<(ostream &o, const vector<T>&obj) {o << "{"; for (int i = 0; i < (int)obj.size(); ++i)o << (i > 0 ? ", " : "") << obj[i]; o << "}"; return o;}
template <class T, class U>ostream &operator<<(ostream &o, const pair<T, U>&obj) {o << "{" << obj.first << ", " << obj.second << "}"; return o;}
template <template <class tmp>  class T, class U> ostream &operator<<(ostream &o, const T<U> &obj) {o << "{"; for (auto itr = obj.begin(); itr != obj.end(); ++itr)o << (itr != obj.begin() ? ", " : "") << *itr; o << "}"; return o;}
void print(void) {cout << endl;}
template <class Head> void print(Head&& head) {cout << head;print();}
template <class Head, class... Tail> void print(Head&& head, Tail&&... tail) {cout << head << " ";print(forward<Tail>(tail)...);}
template <class T> void chmax(T& a, const T b){a=max(a,b);}
template <class T> void chmin(T& a, const T b){a=min(a,b);}
void YN(bool flg) {cout << (flg ? "YES" : "NO") << endl;}
void Yn(bool flg) {cout << (flg ? "Yes" : "No") << endl;}
void yn(bool flg) {cout << (flg ? "yes" : "no") << endl;}


const int NMAX = 100;
vector<vector<int>> edge(NMAX+1);
vector<int> vst(NMAX+1,0),d(NMAX+1,0),f(NMAX+1,0);
int idx = 0;

void dfs(int from){
	if(vst[from]) return;
    ++idx;
    if(!vst[from]) d[from] = idx;
    vst[from] = 1;

    for(auto to:edge[from]){
        if(vst[to]) continue;
        dfs(to);
    }
	idx++;
	f[from] = idx;
}

int main() {
    int N; cin >> N;
	for(int i = 0; i < N; ++i){
        int u,k; cin >> u >> k;
        for(int j = 0; j < k; ++j) {
            int v; cin >> v;
            edge[u].push_back(v);
        }
        sort(edge[u].begin(),edge[u].end());
    }
	for(int i = 1; i <= N; ++i) dfs(i);

    for(int i = 1; i <= NMAX; ++i){
        if(d[i]) cout << i << " " << d[i] << " " << f[i] << endl;
    }


    
    return 0;
}

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

const int MAX_N = 100;

struct Node {
  int v;
  int firstVisitedTime;
  int lastVisitedTime;
  bool visited;
};

void visit(int *count, int n, std::vector<std::list<int> *> *graph, std::vector<struct Node *> *nodes) {
  (*count)++;
  
  struct Node *node = nodes->at(n);

  if (!node->visited) {
    node->firstVisitedTime = *count;
    node->visited = true;
  }  

  //  std::cout << (*count) << " = " << n << std::endl;

  std::list<int> *neighbors = graph->at(n);

  while (!neighbors->empty()) {
    int v = neighbors->front();
    neighbors->pop_front();
    
    if (!nodes->at(v)->visited) {
      visit(count, v, graph, nodes);
    }
  }

  (*count)++;
  node->lastVisitedTime = (*count);

  //  std::cout << (*count) << " = " << n << std::endl;
}

int main(void) {
  std::cin.tie(0);
  std::ios::sync_with_stdio(false);  

  int n = 0;
  std::cin >> n;

  std::vector<std::list<int> *> *graph = new std::vector<std::list<int> *>(n + 1);
  std::vector<struct Node *> *nodes = new std::vector<struct Node *>(n + 1);
  
  for (int i = 1; i <= n; i++) {
    int v = 0;
    std::cin >> v;

    int k = 0;
    std::cin >> k;

    std::list<int> *neighbors = new std::list<int>();

    for (int i = 0; i < k; i++) {
      int a = 0;
      std::cin >> a;

      neighbors->push_back(a);
    }

    graph->at(i) = neighbors;

    struct Node *node = (struct Node *) std::malloc(sizeof(struct Node));

    node->v = i;
    node->firstVisitedTime = 0;
    node->lastVisitedTime = 0;
    node->visited = false;
    
    nodes->at(i) = node;
  }

  int count = 0;
  int start = 1;

  visit(&count, start, graph, nodes);  

  for (std::vector<struct Node *>::iterator iterator = nodes->begin() + 1; iterator != nodes->end(); ++iterator) {
    struct Node *node = *iterator;
        
    std::cout << node->v << " " << node->firstVisitedTime << " " << node->lastVisitedTime << std::endl;
  }
  
  return 0;
}

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

using namespace std;

int n;
vector<vector<int>> g; 
int timeT = 0;
vector<int> d, f;
 
void dfs(int node){
    timeT++;

    if(d[node] == 0){
        d[node] = timeT;
    }

    for(auto next : g[node]){
        if(d[next] == 0){
            dfs(next);
        }
    }
    
    timeT++;
    if(f[node] == 0){
        f[node] = timeT;
    }
    return;
}
    
int main(){
    
    cin >> n;

    d.assign(n + 1, 0);
    f.assign(n + 1, 0);

    g.assign(n + 1, vector<int>());

    for(int i = 0; i < n; i++)
    {
        int nod, numOut;
        cin  >> nod >> numOut;
        for(int j = 0; j < numOut; j++)
        {
            int temp;
            cin >> temp;
            g[nod].push_back(temp);
        }
    }
    
    dfs(1);

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

    return 0;
}