Go: package main

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

type TimeRecord struct {
	discoverTime int
	finishTime   int
}

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	n, err := nextInt(sc)
	if err != nil {
		panic(err)
	}

	timeRecordMap := make([]TimeRecord, n)
	childrenMap := make([][]int, n)
	for i := 1; i <= n; i++ {
		node, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		timeRecordMap[node-1] = TimeRecord{-1, -1}

		childNum, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		childrenMap[node-1] = make([]int, childNum)
		for j := 0; j < childNum; j++ {
			child, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			childrenMap[node-1][j] = child
		}
	}

	timer := 1
	for {
		startNode := findStartNode(childrenMap, timeRecordMap)
		if startNode > 0 {
			visit(startNode, &timer, childrenMap, timeRecordMap)
		} else {
			break
		}
	}
	for k, v := range timeRecordMap {
		fmt.Printf("%d %d %d\n", k+1, v.discoverTime, v.finishTime)
	}
}

func findStartNode(childrenMap [][]int, timeRecordMap []TimeRecord) int {
	x := -1
	for node, timeRecord := range timeRecordMap {
		if timeRecord.discoverTime < 0 {
			x = node + 1
			break
		}
	}
	if x < 0 {
		return -1
	}

	found := false
	i := 0
	for i < len(childrenMap) {
		children := childrenMap[i]
		for j := 0; j < len(children); j++ {
			if children[j] == x {
				x = j + 1
				found = true
				break
			}
		}
		if found {
			i = 0
		} else {
			i++
		}
	}
	return x
}

func visit(currentNode int, timer *int, childrenMap [][]int, timeRecordMap []TimeRecord) {
	if timeRecordMap[currentNode-1].discoverTime > 0 {
		return
	}
	children := childrenMap[currentNode-1]
	timeRecordMap[currentNode-1] = TimeRecord{*timer, timeRecordMap[currentNode-1].finishTime}
	(*timer)++
	for i := 0; i < len(children); i++ {
		visit(children[i], timer, childrenMap, timeRecordMap)
	}
	timeRecordMap[currentNode-1] = TimeRecord{timeRecordMap[currentNode-1].discoverTime, *timer}
	(*timer)++
}

func nextInt(sc *bufio.Scanner) (int, error) {
	sc.Scan()
	return strconv.Atoi(sc.Text())
}

C++: #include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>

using namespace std;

#define WHITE 0
#define GRAY 1
#define BLACK 2
#define N 100

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

int nxt(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 idx){
	for (int i = 0; i < n; ++i) nt[i] = 0;

	stack<int> s; s.push(idx);
	color[idx] = GRAY;
	d[idx] = ++t;

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

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

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

	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;
	}

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

	dfs();
	return 0;
}

C++: #include <cstdio>
#include <stack>
using namespace std;

#define start first
#define end second

static const int NOT   = false;
static const int WHITE = 1;
static const int GRAY  = 2;
static const int BLACK = 3;
static const int N	   = 101;

int  n;
int  VisitedInfo[N];
bool Graph[N][N];
pair< int, int > Time[N];

void dfs( int u );
int  nextNode( int u );

int main()
{

	int u, k, v;

	for( int i = 0; i < N; i++ ) {
		for( int j = 0; j < N; j++ ) Graph[i][j] = NOT;
		VisitedInfo[i] = WHITE;
	}

	scanf( "%d", &n );
	for( int i = 0; i < n; i++ ) {
		
		scanf( "%d %d", &u, &k );
		for( int j = 0; j < k; j++ ) {

			scanf( "%d", &v );
			Graph[u][v] = true;

		}

	}

	dfs( 1 );

	for( int i = 1; i <= n; i++ ) printf( "%d %d %d\n", i, Time[i].start, Time[i].end );

	return 0;

}

void dfs( int u )
{

	int  time = 1, pos, ppos;
	bool brkUpNodeFlg = false;
	stack< int > dfsInfo;

	dfsInfo.push( u );
	Time[u].start  = time;
	VisitedInfo[u] = BLACK;

	while( !dfsInfo.empty() ) {

		ppos = dfsInfo.top();

		if( !brkUpNodeFlg ) pos = nextNode( ppos );

		brkUpNodeFlg = false;

		if( pos != 0 ) {
			if( VisitedInfo[pos] == WHITE ) {

				dfsInfo.push( pos );
				Time[pos].start  = ++time;
				VisitedInfo[pos] = BLACK;

			}
		}
		if( pos == 0 && VisitedInfo[ppos] != WHITE ){

			dfsInfo.pop();
			Time[ppos].end	  = ++time;
			VisitedInfo[ppos] = BLACK;


		}

		if( dfsInfo.empty() ) {
			for( int i = 1; i <= n; i++ ) {
				if( VisitedInfo[i] == WHITE ) {

					pos = i;
					dfsInfo.push( pos );
					Time[pos].start  = ++time;
					VisitedInfo[pos] = BLACK;
					brkUpNodeFlg     = true;
					break;

				}
			}
		}

	}

}

int nextNode( int now )
{

	for( int i = 1; i <= n; i++ ) {
		if( Graph[now][i] && VisitedInfo[i] == WHITE ) return i;
	}

	return 0;

}

C++: #include<bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i) 
#define PI acos(-1)

using namespace std;
using ll = long long;
using P = pair<int, int>;
using LP = pair<ll, ll>;

int dfs(int t, int v, vector<vector<int>> adj, vector<P>& ts) {
    if (ts[v].first != 0) return t;

    t++;
    ts[v].first = t;
    for (auto e : adj[v]) {
        t = dfs(t, e, adj, ts);
    }
    t++;
    ts[v].second = t;
    return t;
}

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

    int n;
    cin>>n;
    vector<vector<int>> adj(n);
    rep(i, n) {
        int u, k, v;
        cin>>u>>k; u--;
        rep(j, k) {
            cin>>v; v--;
            adj[u].push_back(v);
        }
    }

    vector<P> ts(n);
    int t = 0;
    rep(i, n) {
        if (ts[i].first != 0) continue;
        t = dfs(t, i, adj, ts);
    }
    rep(i, n) {
        cout<<i + 1<<" "<<ts[i].first<<" "<<ts[i].second<<endl;
    }
}

C++: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vs = vector<string>;
using msi = map<string, int>;
using mii = map<int, int>;
using psi = pair<string, int>;
using pii = pair<int, int>;
using vlai = valarray<int>;
#define rep(i,n) for(int i=0;i<n;i++)
#define range(i,s,n) for(int i=s;i<n;i++)
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define fs first
#define sc second
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define INF 1E9
#define EPS 1E-9
#define MOD (ll)(1E9+7)
#define PI 3.1415926535897932384

template <class T>ostream &operator<<(std::ostream &o, const vector<T> &v)
{
	rep(i, v.size()) {
		o << (i > 0 ? " " : "") << v[i];
	}
	return o;
}
int n,t=0;
vvi a;
vi d;
vi f;

void Depth(int pos) {
	if (d[pos] == 0) {
		d[pos] = ++t;
	}
	rep(i, n) {
		if (a[pos][i] == 1&&d[i]==0) {
			Depth(i);
		}
	}
	if (f[pos] == 0) {
		f[pos] = ++t;
	}
}


int main() {
	cin >> n;
	a.resize(n, vi(n, 0));
	d.resize(n, 0);
	f.resize(n, 0);
	rep(i, n) {
		int num,m;
		cin >>num >>m;
		rep(i, m) {
			int tmp;
			cin >> tmp;
			a[num - 1][tmp - 1] = 1;
		}
	}
	Depth(0);
	rep(i, n) {
		if (d[i] == 0) {
			Depth(i);
		}
	}
	rep(i, n) {
		cout << i + 1 << " " << d[i] << " " << f[i] << endl;
	}
}