Go: package main

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

var N int
var A [][]int
var t int
var color, d, f []int

const (
	WHITE = iota
	GRAY
	BLACK
)

func dfsVisit(u int) {
	color[u] = GRAY
	t ++
	d[u] = t
	for v:=0; v<N; v++ {
		if A[u][v] == 0 {
			continue
		}
		if color[v] == WHITE {
			dfsVisit(v)
		}
	}
	color[u] = BLACK
	t++
	f[u] = t
}

func dfs() {
	for u:=0; u<N; u++ {
		if color[u] == WHITE {
			dfsVisit(u)
		}
	}
	for u:=0; u<N; u++{
		fmt.Printf("%d %d %d\n", u+1, d[u], f[u])
	}
}


func nextInt(scanner *bufio.Scanner) int {
	scanner.Scan()
	num, _ := strconv.Atoi(scanner.Text())
	return num
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	N = nextInt(scanner)
	color = make([]int, N)
	d = make([]int, N)
	f = make([]int, N)
	A = make([][]int, N)
	for i:=0; i<N; i++{
		A[i] = make([]int, N)
	}
	for i:=0; i<N; i++{
		index := nextInt(scanner) - 1
		cnt := nextInt(scanner)
		for j:=0; j<cnt; j++ {
			v := nextInt(scanner) - 1
			A[index][v] = 1
		}
	}
	dfs()
}

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

#define REP(i,m,n) for(int i=(m); i<(int)(n); i++)
#define RREP(i,m,n) for(int i=(int)(n-1); i>=m; i--)
#define rep(i,n) REP(i,0,n)
#define rrep(i,n) RREP(i,0,n)
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define aut(r,v) __typeof(v) r = (v)
#define each(it,o) for(aut(it,(o).begin()); it!=(o).end(); ++it)
#define reach(it,o) for(aut(it,(o).rbegin()); it!=(o).rend(); ++it)
#define fi first
#define se second
#define debug(...) {cerr<<"[L"<<__LINE__<<"] "; _debug(__VA_ARGS__);}

template<typename T1, typename T2> ostream& operator<<(ostream& o, const pair<T1, T2>& p)
{return o<<"("<<p.first<<", "<<p.second<<")";}
template<typename T>string join(const vector<T>&v, string del=", ")
{stringstream s;rep(i,v.size())s<<del<<v[i];return s.str().substr(del.size());}
template<typename T>ostream& operator<<(ostream& o, const vector<T>&v)
{if(v.size())o<<"["<<join(v)<<"]";return o;}
template<typename T>ostream& operator<<(ostream& o, const vector<vector<T> >&vv)
{int l=vv.size();if(l){o<<endl;rep(i,l){o<<(i==0?"[ ":",\n  ")<<vv[i]<<(i==l-1?" ]":"");}}return o;}
template<typename T>ostream& operator<<(ostream& o, const set<T>& st)
{vector<T> v(st.begin(),st.end());o<<"{ "<<join(v)<<" }";return o;}
template<typename T1, typename T2>ostream& operator<<(ostream& o, const map<T1, T2>& m)
{each(p,m){o<<(p==m.begin()?"{ ":",\n  ")<<*p<<(p==--m.end()?" }":"");}return o;}
inline void _debug(){cerr<<endl;}
template<class First, class... Rest>
void _debug(const First& first, const Rest&... rest){cerr<<first<<" ";_debug(rest...);}

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;

const double PI = (1*acos(0.0));
const double EPS = 1e-9;
const ll INF = 0x3f3f3f3f;
const ll INFL = 0x3f3f3f3f3f3f3f3fLL;
const ll mod = 1e9 + 7;

inline void finput(string filename) {
    freopen(filename.c_str(), "r", stdin);
}

vi g[110];
vi f, d;
int t = 1;

void dfs(int v, int p=-1){
    d[v] = t++;
    for(auto u : g[v]){
        if(u == p || d[u] != 0) continue;
        dfs(u, v);
    }
    f[v] = t++;
};

int main(){
    ios_base::sync_with_stdio(0);
    // finput("./input");
    int n; cin >> n;
    rep(i,n){
        int u,k; cin >> u >> k;
        rep(j,k){
            int v; cin >> v;
            g[u].push_back(v);
        }
    }

    f = vi(n+1), d = vi(n+1);
    REP(i,1,n+1){
        if(d[i] == 0) dfs(i);
    }
    REP(i,1,n+1){
        printf("%d %d %d\n", i, d[i], f[i]);
    }
    return 0;
}

C++: #include <stdio.h>
#include <vector>
#include <list>
#include <map>
#include <array>
#include <memory>
#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cmath>
#include <unordered_map>
#include <stdexcept>


using std::string;
using std::vector;


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// util
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

std::vector<std::string> split(const std::string& input, char delimiter)
{
    std::istringstream stream(input);

    std::string field;
    std::vector<std::string> result;
    while (std::getline(stream, field, delimiter)) {
        result.push_back(field);
    }
    return result;
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// user func
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void printList(const vector<int>& list) {
    // print
    for(int i = 0; i < list.size(); i++){
        printf("%d", list[i]);
        if ( i + 1 != list.size() ) {
            printf(" ");
        }
    }
    printf("\n");
}



//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// logic
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


class Node{
public:
    Node(vector<int> adjacency)
        : adjacency(adjacency) 
    {
        // constructer
    }
    int found = 0;
    int finished = 0;
    vector<int> adjacency;
};

class List{
public:
    List(){
        // 0 番目はダミー
        list.push_back(Node({}));
    }
    void Add(Node&& node){
        this->list.push_back(node);
    }
    void Traverse(){
        for(int i = 1; i < list.size(); i++){
            this->_traverse(i);
        }
    }
    void Print() {
        for (int i = 1; i < list.size(); i++) {
            printf("%d %d %d\n", i, list[i].found, list[i].finished);
        }
    }
private:
    vector<Node> list;
    void _traverse(int index)
    {
        auto current = list[index];
        static int count = 1;

        if (current.found){
            return;
        }

        this->list[index].found = count++;

        for(int i = 0; i < current.adjacency.size(); i++) {
            _traverse(current.adjacency[i]);
        }

        this->list[index].finished = count++;
    }
};

void solve() {
    List list;
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++){
        int value;
        scanf("%d", &value);
        int k;
        scanf("%d", &k);
        vector<int> adjacency(k);
        for(int j = 0; j < k; j++){
            int link;
            scanf("%d", &link);
            adjacency[j] = link;
        }
        list.Add(Node(adjacency));
    }
    list.Traverse();
    list.Print();
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// main
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main() {
    solve();
    return 0;
}

C++: #define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <iostream>
#include <cstdio>
#include <stack>
using namespace std;
stack<int> st;
int  v[102][101], n;
int  time[102][2];
int ct = 1;
inline void search(int t) {
	if(!time[t][0]) time[t][0] = ct++;
	int tf = 0;
	for (int a = 1; a <= n; a++) {
		if (v[t][a]) {
			st.push(a);
			for (int i = 1; i <= n; i++) {
				v[i][a] = 0;
			}
			search(st.top());
			tf = 1;
		}
	}
		
	if(!tf) {
		st.pop();
		time[t][1] = ct++;
		if(!st.empty()) search(st.top());
	}
}
int main() {
	st.push(1);
	int u, k, s;
	cin >> n;
	for (int i = 0; i <= n; i++) {
		for (int j = 0; j <= n; j++) {
			v[i][j] = 0;
		}
	}
	for (int i = 0; i < n; i++) {
		cin >> u;
		cin >> k;
		for (int j = 0; j < k; j++) {
			cin >> s;
			v[u][s] = 1;
		}
	}
	search(1);
	for (int i = 1; i <= n; i++) {
		cout << i << " " << time[i][0] << " " << time[i][1] << endl;
	}
	return 0;
}