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 <bits/stdc++.h>
using ll = long long;
using namespace std;
#define rep(i,n) for(int i=0, i##_len=(int)(n); i<i##_len; i++)
#define reps(i,n) for(int i=1 , i##_len=(int)(n);i<=i##_len;i++)
#define rrep(i,n) for(int i=((int)(n)-1);i>=0;i--)
#define rreps(i,n) for(int i=((int)(n));i>0;i--)
#define all(x) (x).begin(), (x).end()
#define F first
#define S second
#define mp make_pair
#define pb push_back
#define solve(a) ((a)?"Yes":"No")
typedef vector<long long> V;
typedef vector<V> VV;
typedef pair<long long , long long> P;
typedef vector<P> VP;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1;} return 0;}
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1;} return 0;}
const long long INFLL = 1LL<<62;
const int INF = 1<<30;
const double PI=acos(-1);
int func(int serching,vector<vector<int>>&path,vector<pair<int,int>>&data,int no,vector<bool>&has){
    has[serching]=true;
    chmin(data[serching].F,no);
  
  // clog<<serching<<" in : "<<no<<endl;
    no++;
    for(auto itr=path[serching].begin();itr!=path[serching].end();itr++){
        if(has[*itr]==false){
       no= func(*itr,path,data,no,has);
        }
    }
    chmax(data[serching].S, no);
  //  clog << serching <<  " out : " << no << endl;
    return no+1;
}
int main(){
    int n;
    cin >>n;
    vector<vector<int>>path(n);
    vector<bool>has(n,false);
    vector<pair<int,int>>data(n,mp(INF,0));
    queue<int>q;
    q.push(0);
    int at;
    int u,k;
    int bef;
    rep(i,n){
        cin>>u>>k;
        u--;
        rep(j,k){
            cin>>bef;
            bef--;
            path[u].push_back(bef);
         //   clog<<u<< " -> "<<bef<<endl;
        }
    }
    rep(i,u){
        sort(all(path[i]));
    }
    int no=1;
    rep(i,n){
        if(has[i]==false){
       no= func(i,path,data,no,has);
        }
    }
    rep(i,n){
        printf("%d %d %d\n",i+1,data[i].F,data[i].S);
    }
}

C++: /*
 * ALDS1_11_B.cpp
 *
 *  Created on: May 5, 2018
 *      Author: 13743
 */

#include<iostream>
#include<vector>

using namespace std;

int d[101];
int f[101];
int time;

void dfsRec(vector<int>* a, int n, int v) {
	if(d[v] > 0) return;
	time++;
	d[v] = time;
	for(int &x:a[v]) {
		dfsRec(a, n, x);
	}
	time++;
	f[v] = time;
}

int main() {
	int n;
	vector<int> adj[101];

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

	dfsRec(adj, n, 1);

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

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

void dfs_init();
void dfs(int u);

int n,**List,*deg,*d,*f;
bool **M;
string *color;
int vertex;
int tm;

int main(){
	cin>>n;
	List = new int*[n]; M = new bool*[n]; deg = new int[n]; color = new string[n]; d = new int[n]; f = new int[n];
	for(int i=0;i<n;i++) List[i] = new int[n]; for(int i=0;i<n;i++) M[i] = new bool[n];
	for(int i=0;i<n;i++){
		List[i] = List[i]-1;
		M[i] = M[i]-1;
	}
	List = List-1; M = M-1; deg = deg-1; color = color-1; d = d-1; f = f-1;

	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			M[i][j] = false;
		deg[i] = 0; d[i] = 0; f[i] = 0;
	}
	
	int k;
	for(int i=1;i<=n;i++){
		cin>>vertex>>k;
		for(int j=1;j<=k;j++){
			cin>>List[vertex][j];
			M[vertex][List[vertex][j]] = true;
		}
	}

	dfs_init();

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

	for(int i=1;i<=n;i++){
		delete [] (List[i]+1); delete [] (M[i]+1);
	}
	delete [] (List+1); delete [] (M+1);
	delete [] (deg+1); delete [] (color+1); delete [] (d+1); delete [] (f+1);
	cin.get(); cin.get();
}

void dfs_init(){
	for(int i=1;i<=n;i++) color[i] = "WHITE";
	tm = 0;
	for(int i=1;i<=n;i++){
		if(color[i]=="WHITE"){
			dfs(i);
		}
	}
}

void dfs(int u){
	color[u] = "GRAY";
	d[u] = ++tm;
	for(int v=1;v<=n;v++){
		if(M[u][v]==false) continue;
		if(color[v]=="WHITE"){
			dfs(v);
		}
	}
	color[u] = "BLACK";
	f[u] = ++tm;
}

C++: //aizu
#include <iostream>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;

vector <int> v[101];

pair <int, int> af[101];

bitset <101> viz;

int cnt;

void DFS(int nod)
{
    cnt++;
    af[nod].first = cnt;
    viz[nod] = 1;

    for (size_t i = 0; i < v[nod].size(); ++i)
    {
        if (viz[v[nod][i]] == 0)
            DFS(v[nod][i]);
    }
    cnt++;
    af[nod].second = cnt;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(NULL);

    int n, u, k, ind;
    cin >> n;
    for (int i = 1; i <= n; ++i)
    {
        cin >> u >> k;
        for (int j = 1; j <= k; ++j)
        {
            cin >> ind;
            v[u].push_back(ind);
        }
        sort(v[u].begin(), v[u].end());
    }

    for (int i = 1; i <= n; ++i)
        if (viz[i] == 0)
            DFS(i);

    for (int i = 1; i <= n; ++i)
        cout << i << " " << af[i].first << " " << af[i].second << "\n";
    return 0;
}