Go: package main

/*
深さ優先探索
*/

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

func main() {
	scanner := makeScanner(8192)
	n := eGetInt(scanner)
	g := make([][]int, n+1)
	for i := 1; i < n+1; i++ {
		ints := eGetInts(scanner)
		num, vcount := ints[0], ints[1]
		g[i] = make([]int, vcount)
		for j := 0; j < vcount; j++ {
			g[num][j] = ints[j+2]
		}
	}
	hist := make([]struct{ d, f int }, n+1)
	t := 0
	var visit func(int)
	visit = func(num int) {
		if hist[num].d == 0 {
			stack := []int{}
			t++
			hist[num].d = t
			stack = append(stack, num)
			for len(stack) > 0 {
				// トップを訪問する
				top := stack[len(stack)-1]
				for i := 0; i < len(g[top]); i++ {
					if hist[g[top][i]].d == 0 {
						t++
						hist[g[top][i]].d = t
						stack = append(stack, g[top][i])
						goto endloop
					}
				}
				// 訪問場所がなくなったら
				// pop
				stack = stack[0 : len(stack)-1]
				t++
				hist[top].f = t
			endloop:
			}
		}
	}
	for i := 1; i < n+1; i++ {
		visit(i)
	}
	for i := 1; i < n+1; i++ {
		fmt.Println(i, hist[i].d, hist[i].f)
	}
}

////////////////////////////////////////////////////////////////////////////////
// ライブラリ
////////////////////////////////////////////////////////////////////////////////
func makeScanner(maxByte int) *bufio.Scanner {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Buffer(make([]uint8, 0, 8192), maxByte)
	return scanner
}
func makeWordScanner() *bufio.Scanner {
	scanner := makeScanner(8192)
	scanner.Split(bufio.ScanWords)
	return scanner
}
func eGetLine(r *bufio.Scanner) string {
	if r.Scan() {
		return r.Text()
	}
	err := r.Err()
	if err != nil {
		log.Fatal(err)
	}
	// EOF
	return ""
}
func eGetInt(r *bufio.Scanner) int {
	line := eGetLine(r)
	return eAtoi(line)
}
func eGetInt64(r *bufio.Scanner) int64 {
	line := eGetLine(r)
	return eAtoInt64(line)
}
func eGetFields(r *bufio.Scanner) []string {
	line := eGetLine(r)
	return strings.Fields(line)
}
func eGetInts(r *bufio.Scanner) []int {
	fields := eGetFields(r)
	ints := make([]int, len(fields))
	for i := 0; i < len(ints); i++ {
		ints[i] = eAtoi(fields[i])
	}
	return ints
}
func eGetInt64s(r *bufio.Scanner) []int64 {
	fields := eGetFields(r)
	ints := make([]int64, len(fields))
	for i := 0; i < len(ints); i++ {
		ints[i] = eAtoInt64(fields[i])
	}
	return ints
}
func eGetChars(r *bufio.Scanner) []string {
	line := eGetLine(r)
	return strings.Split(line, "")
}
func eAtoi(s string) int {
	n, err := strconv.Atoi(s)
	if err != nil {
		log.Fatal(err)
	}
	return n
}
func eAtoInt64(s string) int64 {
	n, err := strconv.ParseInt(s, 10, 64)
	if err != nil {
		log.Fatal(err)
	}
	return n
}

C++: #include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <algorithm>
using namespace std;

bool rel[128][128];
int disc[128];
int comp[128];
int n, turn = 0;

void dfs(int visit, vector<int> &log){
	if(find(log.begin(), log.end(), visit) == log.end()){
		log.push_back(visit);
		disc[visit] = ++turn;
		for(int i = 1; i <= n; i++){
			if(rel[visit][i] && find(log.begin(), log.end(), i) == log.end()) dfs(i, log);
		}
		comp[visit] = ++turn;
	}
}

int main() {
	scanf("%d", &n);
	
	for(int i = 1; i <= n; i++){
		int u, k;
		scanf("%d %d", &u, &k);
		
		for(int j = 1; j <= n; j++){
			rel[u][j] = false;
		}
		while(k--){
			int v;
			scanf("%d", &v);
			rel[u][v] = true;
		}
	}
	
	vector<int> visited;
	for(int i = 1; i <= n; i++){
		dfs(i, visited);
	}
	
	for(int i = 1; i <= n; i++){
		printf("%d %d %d\n", i, disc[i], comp[i]);
	}
	return 0;
}

C++: #include<iostream>
#define FOR(i,a,b) for (int i=(a);i<(b);i++)
using namespace std;
int G[100][100] = {};
int time = 0;
typedef struct ANS
{
	int id, t, e;
	bool done;
};

void rec(ANS a[],int t)
{
	::time++;
	a[t].t = ::time;
	a[t].done = true;
	FOR(i, 0, 100)
	{
		if (G[t][i] == 1 && a[i].done == false)
		{
			rec(a, i);
		}
	}
	::time++;
	a[t].e = ::time;
}

int main()
{
	ANS ans[101];
	int n;
	cin >> n;
	FOR(i, 0, n)
	{
		ans[i].id = i + 1;
		ans[i].done = false;
		int u, m;
		cin >> u >> m;
		FOR(j, 0, m)
		{
			int l;
			cin >> l;
			G[u - 1][l - 1] = 1;
		}
	}
	rec(ans, 0);
	FOR(i, 0, n)
	{
		cout << ans[i].id << " " << ans[i].t << " " << ans[i].e << endl;
	}
	return 0;
}

C++: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
// #define int long long

template <class T>
bool INRANGE(T x, T a, T b) { return a <= x && x <= b; }
template <class T>
inline bool chmin(T &a, T b)
{
    if (a > b)
    {
        a = b;
        return true;
    }
    return false;
}
template <class T>
inline bool chmax(T &a, T b)
{
    if (a < b)
    {
        a = b;
        return true;
    }
    return false;
}

#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, a, b) for (int i = (a); i < (b); ++i)
#define RFOR(i, a, b) for (int i = (a); i >= (b); --i)
#define ALL(v) (v).begin(), (v).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" \
                      << " " << __FILE__ << endl;

typedef vector<int> vi;
typedef vector<string> vs;
typedef vector<vi> vvi;
typedef pair<int, int> pii;

int t = 1;
vvi to;
vi d, f;
vector<bool> visited;

void dfs(int i) {
    i--;
    if (visited[i]) return;
    visited[i] = true;

    d[i] = t;
    t++;
    sort(ALL(to[i]));

    for (int nv : to[i]) {
        //debug(nv)
        
        dfs(nv);
    }
    
    f[i] = t;
    t++;
}
 
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    int N;
    cin >> N;
    to = vvi(N, vi());
    REP(i, N) {
        int k, idx;
        cin >> idx >> k;
        idx--;
        to[i].resize(k);
        REP(j, k) cin >> to[idx][j];
    }
    // debug(N)

    d.resize(N);
    f.resize(N);
    visited = vector<bool>(N, false);

    
    REP(i, N){
        if (f[i] == 0) dfs(i+1);
    } 

    REP(i, N) {
        cout << i+1 << " " << d[i] << " " << f[i] << endl;
    }

    return 0;
}

C++: /*
 * b.cc: 
 */

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>

using namespace std;

/* constant */

const int MAX_N = 100;

/* typedef */

typedef vector<int> vi;

/* global variables */

vi nbrs[MAX_N];
int ds[MAX_N], fs[MAX_N];

/* subroutines */

int dfs(int u, int t) {
  ds[u] = ++t;

  for (int i = 0; i < nbrs[u].size(); i++) {
    int &v = nbrs[u][i];
    if (! ds[v]) t = dfs(v, t);
  }

  return (fs[u] = ++t);
}

/* main */

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

  for (int i = 0; i < n; i++) {
    int u, k;
    cin >> u >> k;
    u--;

    for (int j = 0; j < k; j++) {
      int v;
      cin >> v;
      v--;
      nbrs[u].push_back(v);
    }
  }

  int t = 0;
  for (int i = 0; i < n; i++)
    if (! ds[i]) t = dfs(i, t);

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

  return 0;
}