Go: package main

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

const (
	initialBufSize = 100000
	maxBufSize     = 1000000
)

var sc *bufio.Scanner

func initScanner(r io.Reader) *bufio.Scanner {
	buf := make([]byte, initialBufSize)

	sc := bufio.NewScanner(r)
	sc.Buffer(buf, maxBufSize)
	sc.Split(bufio.ScanWords) // bufio.ScanLines
	return sc
}

func main() {
	sc = initScanner(os.Stdin)
	resolve(parseProblem())
}

type graph struct {
	size  int
	edges [][]int
}

func parseProblem() *graph {
	n := scanInt(sc)
	g := &graph{
		size:  n,
		edges: make([][]int, n),
	}
	for i := 0; i < g.size; i++ {
		_ = scanInt(sc)
		k := scanInt(sc)
		g.edges[i] = make([]int, k)
		for j := 0; j < k; j++ {
			g.edges[i][j] = scanInt(sc) - 1
		}
	}
	return g
}

func resolve(g *graph) {
	ds := make([]int, g.size)
	fs := make([]int, g.size)
	time := 0
	for i := 0; i < len(ds); i++ {
		if ds[i] == 0 {
			time++
			time = _dfs(ds, fs, time, g, i)
		}
	}
	for i := 0; i < len(ds); i++ {
		fmt.Println(i+1, ds[i], fs[i])
	}
	return
}

func _dfs(ds, fs []int, time int, g *graph, idx int) int {
	ds[idx] = time
	for _, next := range g.edges[idx] {
		if ds[next] > 0 {
			continue
		}
		time++
		time = _dfs(ds, fs, time, g, next)
	}
	time++
	fs[idx] = time
	return time
}

// snip-scan-funcs
func scanInt(sc *bufio.Scanner) int {
	sc.Scan()
	i, _ := strconv.Atoi(sc.Text())
	return int(i)
}
func scanString(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

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

#define _CRT_SECURE_NO_WARNINGS

#define REP(i, n) for(decltype(n) i = 0; i < (n); i++)
#define REP2(i, x, n) for(decltype(x) i = (x); i < (n); i++)
#define REP3(i, x, n) for(decltype(x) i = (x); i <= (n); i++)
#define RREP(i, n) for (decltype(n) i = (n) - 1; i >= 0; i--)

#define ALL(a) (a).begin(),(a).end()
#define SORT(c) sort((c).begin(),(c).end())
#define DESCSORT(c) sort(c.begin(), c.end(), greater<int>())

using namespace std;

const int INF = 1000000000;
const double PI = 3.1415926535897932384626433832795;

// N, E, S, W
const int dx[4] = { -1, 0,  1,  0 };
const int dy[4] = { 0, 1,  0, -1 };

using LL = long long int;
using LD = long double;
using pii = pair<int, int>;
using pdd = pair<double, double>;
using pll = pair<LL, LL>;
using vi = vector<int>;
using vd = vector<double>;
using vs = vector<string>;
using vvi = vector<vi>;
using vll = vector<LL>;

//==============================================
int n, tt = 0;
vvi M;
vi D, F, searchStatus;

// ??±???????????¢?´¢
void antDfs(int u) {
	searchStatus[u] = 1;

	// ?????????(??????)??????????????????
	D[u] = ++tt;
	REP3(i, 1, n) {
		if (M[u][i] == 0) continue;

		if (searchStatus[i] == -1) {
			antDfs(i);
		}
	}
	// ?????????(??????)???????????????
	F[u] = ++tt;

	// ??¢?´¢??????
	searchStatus[u] = 1;
}

void print() {
	REP3(i, 1, n) {
		cout << i << " " << D[i] << " " << F[i] << "\n";
	}
}

void solve() {

	REP3(i, 1, n) {
		if (searchStatus[i] == -1) {
			//????¨???????i????§??????¨????????±???????????¢?´¢?????????
			antDfs(i);
		}
	}

	// ??????
	print();
}

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

	cin >> n;
	
	M.resize(n + 1, vi(n + 1));
	D.resize(n + 1);
	F.resize(n + 1);

	// ??¢?´¢??¶??????????????? (?????¢?´¢)
	searchStatus.resize(n + 1, -1);

	
	int u, k, v;
	REP3(i, 1, n) {
		cin >> u >> k;
		REP3(j, 1, k) {
			cin >> v;
			M[u][v] = 1;
		}
	}

	solve();
	return 0;
}

C++: #include "bits/stdc++.h"
#include "math.h"
 
using namespace std;
typedef long long ll;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<int> vin;
typedef pair<ll,ll> P;
typedef vector<P> vp;
#define rep(i,a,b) for(ll i=(a);i<(b);++i)
#define SIZE(a) int((a).size())
#define out(a) cout<<(a)<<endl;
const int INF=INT_MAX;
const int MAX = 510000;
const ll MOD = 1000000007;
vll d(100),f(100);
ll t=0;
void dfs(vvll g,vb &v,ll x){
  v[x]=true;
  d[x]=++t;
  
  rep(i,0,g[x].size()){
    if(!v[g[x][i]]){
      dfs(g,v,g[x][i]);
    }
  }
  f[x]=++t;
  
}
int main(){
  ll n;cin>>n;
  vvll g(n,vll(0));
  vb visited(n,false);
  rep(i,0,n){
    ll m,k;cin>>m>>k;
    m--;
    rep(j,0,k){
      ll x;cin>>x;
      g[m].push_back(--x);
    }
  }
  rep(i,0,n){
    if(!visited[i]){
      dfs(g,visited,i);
    }
  }
  
  rep(i,0,n){
    cout<<i+1<<" "<<d[i]<<" "<<f[i]<<endl;
  }
}

C++: 
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstring>
#include <stack>
#define fre freopen("//home//yanjiewei//CLionProjects//cin.txt", "r", stdin)


using namespace std;

int map[105][105], vis[105];
stack <int> s;

int main(){
//    fre;
    memset(map, 0, sizeof(map));
    memset(vis, 0, sizeof(vis));
    int n;
    cin>> n;
    int u, k, v;
    for(int i = 0; i < n; i++){
        cin>> u;
        cin>> k;
        while(k--){
            cin>> v;
            map[u][v] = 1;
        }
    }
    int t = 1, now = 1;
    int d[105], f[105];
    s.push(1), d[1] = t, vis[1] = 1;
    while(!s.empty()){
        int p = 0;
        now = s.top();
        for(int i = 1; i <= n; i++){
            if(map[now][i] == 1 && vis[i] == 0) {
                s.push(i);
                t++, d[i] = t;
                vis[i] = 1;
                p++;
                break;
            }
        }
        if(p == 0){
            int out = s.top();
            s.pop();
            t++, f[out] = 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 rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define INF 1000000007
typedef int64_t in;
typedef long long ll;

int n;
int m[105][105] = {};
int color[105] = {};
int d[105] = {};
int f[105] = {};
int u,k;
int v;
int t=0;
int nt[105] = {};

int next(int u){
    REP(v, nt[u], n){
        nt[u] = v + 1;
        if(m[u][v]) return v;
    }
    return -1;
}

void dfs(int u){
    rep(u,n){
        if(color[u] == 0){
            stack<int> S;
            color[u] = 1;
            d[u] = ++t;
            S.push(u);

            while(!S.empty()){
                u = S.top();
                v = next(u);
                if(v != -1){
                    if(color[v] == 0){
                        S.push(v);
                        color[v] = 1;
                        d[v] = ++t;
                    }
                }else{
                    S.pop();
                    color[u] = 2;
                    f[u] = ++t;
                }
                
            }
        }
    }

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

int main(){
    cin >> n;
    
    /*rep(i,n){
        color[i] = 0;
    }*/

    rep(i,n){
        cin >> u >> k;
        for(int i=0; i<k; i++){
            cin >> v;
            m[u-1][v-1] = 1;
        }
    }

    dfs(0);
}