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>
#define rep(i, n) for (int i = 0; i < (n); i++)
using namespace std;
#define WHITE 0
#define GRAY 1
#define BLACK 2
typedef long long LL;
const int MAXN = 110;
int n, mapp[MAXN][MAXN], color[MAXN], d[MAXN], f[MAXN], tt;

void dfs_visit(int u) {
	color[u] = GRAY;//参照したことを示す
	d[u] = ++tt; //発見した時間を示す　0からなので足してから
	for(int i = 0; i < n; i++) {
		if(mapp[u][i] == 1 && color[i] == WHITE) {//u,i間に辺があること,iが未探訪を確認
			dfs_visit(i);
		}
	}
	color[u] = BLACK;//uに関して終わったことを示す
	f[u] = ++tt; //終了した時間を示す　足してから

}

void dfs() {
	tt = 0;
	memset(color, 0, sizeof(color));//探訪情報をリセット
	for(int i = 0; i < n; i++) {
		if(color[i] == WHITE) {//未探訪なら探索
			dfs_visit(i);
		}
	}
	for(int i = 0; i < n; i++) {
		printf("%d %d %d\n", i+1, d[i], f[i]);
	}
}

int main() {
	int u, v, k;
	cin >> n;
	memset(mapp, 0, sizeof(mapp));//木情報をリセット
	for(int i = 0; i < n; i++) {
		cin >> u >> k;
		u--; //0から考えているのでノードの番号を1減らす
		while(k--) {
			cin >> v;
			v--;
			mapp[u][v] = 1;//uとvに辺があることを示す
		}
	}
	dfs();
	return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define INF (1LL<<50)
#define MOD 1000000007

vector<vector<int>> v;
vector<bool> seen;
vector<int> d,f;
int t = 0;

void dfs(int u,int &t){
    t++;
    d[u] = t; // 初訪問時の時刻
    seen[u] = true;
    for(int i=0;i<v[u].size();i++){
        if(seen[v[u][i]]) continue;
        dfs(v[u][i],t);
    }
    t++;
    f[u] = t;
}

int main(){
    int n;
    cin >> n;

    v.resize(n+1);
    seen.resize(n+1);
    d.resize(n+1);
    f.resize(n+1);
    rep(i,n+1) seen[i] = false;

    rep(i,n){
        int u,k;
        cin >> u >> k;
        rep(j,k){
            int tmp;
            cin >> tmp;
            v[u].push_back(tmp);
        }
    }
    // 深さ優先探索で探索する.
    for(int i=1;i<=n;i++){
        if(seen[i])continue;
        dfs(i,t);
    }
    for(int i=1;i<=n;i++){
        cout << i << " " << d[i] << " " << f[i] << endl;
    }
    return 0;
}

C++: #include <bits/stdc++.h>

using namespace std;

#define ll long long
typedef complex<double> P;

int main() {
  int n; cin >> n;
  int adj[n][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;
      adj[u-1][v-1] = 1;
    }
  }

  int d[n] = {};
  int f[n] = {};
  int t = 1;

  stack<int> st;
  st.push(0);

  while (!st.empty()) {
    int v = st.top();

    if(d[v] == 0) {
      d[v] = t;
    }

    for (int i = 0; i < n; i++) {
      if(adj[v][i] == 1 && d[i] == 0) {
        st.push(i);
        break;
      }
    }

    if(st.top() == v) {
      f[v] = t+1;
      st.pop();
    }

    t++;
  }

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

}

C++: // -*- mode:c++; coding:utf-8; c-basic-offset:2; -*-
// ALDS1_11_B: Depth First Search

#include <algorithm>
#include <cstdio>
#include <stack>
#include <utility>

using uint = unsigned int;

class Graph {
  const uint n_;
  uint* const g_;
  std::pair<uint, uint>* const visited_;
  uint time_;
  
public:
  Graph(uint n) : n_(n),
                  g_(new uint[(n_*n_)]),
                  visited_(new std::pair<uint, uint>[n_])
  {
    std::fill(g_, g_+(n_*n_), 0u);
  }

  ~Graph()
  {
    delete[] g_;
    delete[] visited_;
  }
  
  uint* operator [](uint i) const { return g_+(n_*i); }

  std::pair<uint, uint>* visited() const { return visited_; }

  void dfs()
  {
    init_visited();
    for (auto i = 0u; i < n_; ++i) {
      if (visited_[i].first) continue;
      inner_dfs(i);
    }
  }

private:
  void init_visited()
  {
    time_ = 0u;
    for (auto i = 0u; i < n_; ++i) {
      visited_[i].first = 0u;
    }
  }

  void inner_dfs(uint i)
  {
    std::stack<uint> s;
    s.push(i);
    visited_[i].first = time_++;
    auto last_visited = i;
  outer_loop:
    while (!s.empty()) {
      auto j = s.top();
      for (auto k = last_visited+1; k < n_; ++k) {
        if ((*this)[j][k] && !visited_[k].first) {
          s.push(k);
          visited_[k].first = time_++;
          goto outer_loop;
        }
      }
      s.pop();
      visited_[j].second = time_++;
      last_visited = j;
    }
  }
};

int main()
{
  uint n;
  std::scanf("%u", &n);

  Graph g(n);

  uint u, k, v;
  for (auto i = 0u; i < n; ++i) {
    std::scanf("%u %u", &u, &k);
    for (auto j = 0u; j < k; ++j) {
      std::scanf("%u", &v);
      g[u-1][v-1] = 1;
    }
  }

  g.dfs();
  auto visited = g.visited();
  for (auto i = 0u; i < n; ++i) {
    std::printf("%u %u %u\n", i+1, visited[i].first+1, visited[i].second+1);
  }
}

// eof

C++: #include <bits/stdc++.h>
using namespace std;
#define WHITE 0
#define GRAY 1
#define BLACK 2

int M[101][101];
int d[101], f[101];
int searchPos[101];
int color[101];
int tt = 0;
int n;
stack<int> s;

int nextPoint(int curPoint){
    for(int i=searchPos[curPoint];i<n;++i){
        searchPos[curPoint] += 1;
        if(M[curPoint][i]==1 && color[i] == WHITE){
            return i;
        }
    }
    return -1;
}

void dfs(int point){
    d[point] = ++tt;
    color[point] = GRAY;
    while(1){
        int next = nextPoint(point);
        if(next != -1){
            dfs(next);
        }
        else{
            f[point] = ++tt;
            color[point] = BLACK;
            return;
        }
    }
}

int main(){
    int u, z, y;
    scanf("%d",&n);
    for(int i=0;i<n;++i){
        searchPos[i] = 0;
        color[i] = WHITE;
        for(int j=0;j<n;++j){
            M[i][j] = 0;
        }
    }
    for(int i=0;i<n;++i){
        cin >> u >> z;
        for(int j=0;j<z;++j){
            cin >> y;
            M[u-1][y-1] = 1;
        }
    }

    dfs(0);
    for(int i=0;i<n;++i){
        if(color[i]==WHITE){
            dfs(i);
        }
    }
    for(int i=0;i<n;++i){
        printf("%d %d %d\n",i+1,d[i],f[i]);
    }
    return 0;
}

C++: #include<cstdio>
#define MAX_N 100
#define WHITE 0
#define GRAY 1
#define BLACK 2

int n, u, k, v;
int adj[MAX_N][MAX_N];
int color[MAX_N], d[MAX_N], f[MAX_N], tt;

void dfs_visit(int num){
	color[num] = GRAY;
	d[num] = ++tt;
	for(int i = 0; i < n; i++){
		if(adj[num][i] == 0) continue;
		if(color[i] == WHITE){
			dfs_visit(i);
		}
	}
	color[num] = BLACK;
	f[num] = ++tt;
}

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

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

int main(void){
	scanf("%d", &n);

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

	for(int i = 0; i < n; i++){
		scanf("%d", &u);
		u -= 1;
		scanf("%d", &k);
		for(int j = 0; j < k; j++){
			scanf("%d", &v);
			v -= 1;
			adj[u][v] = 1;
		}
	}

	dfs();

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

	return 0;
}