Go: package main

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

// repr state of visited node
// WHITE yet visit
// GEAY  visiting
// BLACK visited
const (
	WHITE int = iota
	GRAY
	BLACK
)

type dfsGraph struct {
	g      [][]int
	colors []int
	stime  []int // Start time of visiting node
	ftime  []int // Finish time of visiting node
}

var time int

func makeAdjList() [][]int {
	var n int
	fmt.Scanf("%d", &n)

	adj := make([][]int, n)
	for i := 0; i < n; i++ {
		adj[i] = make([]int, n)
	}

	sc := bufio.NewScanner(os.Stdin)
	for i := 0; i < n; i++ {
		sc.Scan()
		nodeInfo := strings.Split(sc.Text(), " ")
		outDegree, _ := strconv.Atoi(nodeInfo[1])

		if outDegree > 0 {
			for k := 0; k < outDegree; k++ {
				j, _ := strconv.Atoi(nodeInfo[k+2])
				j-- // convert 1 based to 0 based
				adj[i][j] = 1
			}
		}
	}

	return adj
}

func (dg dfsGraph) dfsVisit(u int) {
	// 頂点uを訪問中に設定
	dg.colors[u] = GRAY
	time++
	dg.stime[u] = time

	// uの隣接nodeを訪問
	for v := 0; v < len(dg.g); v++ {
		if dg.g[u][v] == 0 {
			continue // 辺がなければスキップ
		}

		// vが未訪問なら訪問
		if dg.colors[v] == WHITE {
			dg.dfsVisit(v)
		}
	}

	// 頂点uを訪問済みに設定
	dg.colors[u] = BLACK
	time++
	dg.ftime[u] = time
}

func (dg dfsGraph) dfs() {
	for i := 0; i < len(dg.g); i++ {
		if dg.colors[i] == WHITE {
			dg.dfsVisit(i)
		}
	}
}

func (dg dfsGraph) printDfsTime() {
	for i := 0; i < len(dg.g); i++ {
		fmt.Printf("%d %d %d\n", i+1, dg.stime[i], dg.ftime[i])
	}
}

func main() {
	adj := makeAdjList()
	colors := make([]int, len(adj))
	stime := make([]int, len(adj))
	ftime := make([]int, len(adj))
	graph := dfsGraph{adj, colors, stime, ftime}
	graph.dfs()
	graph.printDfsTime()
}

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

using namespace std;

static const int N = 100;
static const int WHITE = 0;
static const int GRAY = 1;
static const int BLACK = 2;

int n, M[N][N];
int color[N], d[N], f[N], tt;
int nt[N];

int next(int u) {
  for (int v = nt[u]; v < n; v++) {
    nt[u] = v + 1;
    if (M[u][v]) {
      return v;
    }
  }
  return -1;
}

void dfs_visit(int r) {
  for (int i = 0; i < n; i++) {
    nt[i] = 0;
  }

  stack<int> S;
  S.push(r);
  color[r] = GRAY;
  d[r] = ++tt;

  while(!S.empty()) {
    int u = S.top();
    int v = next(u);
    if (v != -1) {
      if (color[v] == WHITE) {
        color[v] == GRAY;
        d[v] = ++tt;
        S.push(v);
      }
    } else {
      S.pop();
      color[u] = BLACK;
      f[u] = ++tt;
    }
  }
}

void dfs() {
  for (int i = 0; i < n; i++) {
    color[i] = WHITE;
    nt[i] = 0;
  }
  tt = 0;

  for (int u = 0; u < n; u++) {
    if (color[u] == WHITE) {
      dfs_visit(u);
    }
  }

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

int main() {

  cin >> n;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      M[i][j] = 0;
    }
  }

  int u, k, v;
  for (int i = 0; i < n; i++) {
    cin >> u >> k;
    u--; // to 0 origin
    for (int j = 0; j < n; j++) {
      cin >> v;
      v--; // to 0 origin
      M[u][v] = 1;
    }
  }

  dfs();

  return 0;
}

C++: #include <bits/stdc++.h>
#define LOOP(n) for (int _i = 0; _i < (n); _i++)
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define RREP(i, n) for (int i = (n); i >= 0; --i)
#define FOR(i, r, n) for (int i = (r); i < (n); ++i)
#define ALL(obj) begin(obj), end(obj)
using namespace std;
using ll = long long;
using ull = unsigned long long;

const int INF = 2100100100;
const int MOD = 1e9 + 7;

// 多次元 vector 生成
template <class T>
vector<T> make_vec(size_t a) {
    return vector<T>(a);
}
template <class T, class... Ts>
auto make_vec(size_t a, Ts... ts) {
    return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}
template <class T>
bool chmax(T &a, const T &b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
bool chmin(T &a, const T &b) {
    if (b < a) {
        a = b;
        return 1;
    }
    return 0;
}

using Graph = vector<vector<int>>;

int N, M, K, Q;
int t;
int used[200];
void dfs(const Graph &G, vector<tuple<int, int, int>> &ans, int node) {
    t++;
    int d = t;
    used[node] = 1;
    for (auto v : G[node]) {
        if (used[v] == 0) {
            dfs(G, ans, v);
        }
    }
    t++;
    int f = t;
    ans.push_back(make_tuple(node, d, f));
}

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

    cin >> N;
    Graph G(N);
    memset(used, 0, sizeof(used));
    REP(i, N) {
        int u, k;
        cin >> u >> k;
        u--;
        REP(j, k) {
            int v;
            cin >> v;
            v--;
            G[i].push_back(v);
        }
        sort(ALL(G[i]));
    }

    vector<tuple<int, int, int>> ans;
    t = 0;
    REP(u, N) {
        if (used[u] != 1) {
            dfs(G, ans, u);
        }
    }
    sort(ALL(ans));

    REP(i, (int)ans.size()) { cout << get<0>(ans[i]) + 1 << " " << get<1>(ans[i]) << " " << get<2>(ans[i]) << endl; }

    return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;

#define debug(x) cout <<"DEBUG"<<" "<< #x << ":" << x << '\n'

// n回繰り返し
#define rep(i,n) for(int i = 0; i < ((int)(n)); i++)   // 0-indexed昇順
#define rep1(i,n) for(int i = 1; i <= ((int)(n)); i++) // 1-indexed昇順
#define rrep(i,n) for(int i = ((int)(n)-1); i >= 0; i--)  // 0-indexed降順
#define rrep1(i,n) for(int i = ((int)(n)); i >= 1; i--)   // 1-indexed降順
#define all(x) (x).begin(),(x).end()

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<vi> vii;  // 2次元配列
typedef vector<ll> vll;
typedef vector<double> vd;
typedef pair<int, int> PII;

template<typename T>
using vec = vector<T>;
template<class T>
using maxheap = std::priority_queue<T>;
template<class T>
using minheap = std::priority_queue<T, std::vector<T>, std::greater<T>>;

template<class T,class U> inline bool chmax(T &a, const U &b){if(a<b){a=b;return 1;}return 0;}
template<class T,class U> inline bool chmin(T &a, const U &b){if(a>b){a=b;return 1;}return 0;}

const ld Pi = std::acos(-1.0L);
const ll infll = (1LL<<62)-1;
const int inf = (1<<30)-1;
const int mod = 1000000007;
// const int mod = 998244353;

/*GRAPH_TEMPLATE=============================================*/
template<typename T>
class Edge {
public:
    int srch; //searched?探索状態記録「null = -1」
    int to; //辺の行き先
    T cost; //辺の重み
    Edge(int t, T w) : srch(-1), to(t), cost(w) {}
    Edge(int t, T w, int src) : srch(src), to(t), cost(w) {}
};
template<typename T>
using W_Graph = std::vector<std::vector<Edge<T>>>;   //重み付きグラフ
using Graph = std::vector<std::vector<int>>;         //通常グラフ
template<typename T>
using Matrix = std::vector<std::vector<T>>;          //隣接行列(使わなさそう...)


vi d,f;
Graph g;
int TIME;
/*FUNCs=================================================*/
void recursive(int u) {
    d[u] = ++TIME;
    for(auto &v : g[u]) {
        if(d[v] != 0) continue;
        recursive(v);
    }
    f[u] = ++TIME;
}

/*MAIN==================================================*/
signed main(){
    int _StartTime_ = clock();
    cin.tie(nullptr);
    ios::sync_with_stdio(false);   //cin cout 高速化
    // cout << fixed << setprecision(15);

    int n; cin >> n;
    d.resize(n+1), f.resize(n+1);
    g.resize(n+1);

    rep(i,n) {
        int u,v; cin >> u;
        u;
        g[0].push_back(u);
        int k; cin >> k;
        rep(j,k) {
            cin >> v;
            v;
            g[u].push_back(v);
        }
    }

    TIME = -1;
    recursive(0);

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

    // printf("ExcutionTime: %d /ms\n",1000*(int)((clock()-_StartTime_)/CLOCKS_PER_SEC));
}