Go: package main

import (
	"fmt"
)

func main() {
	var n int
	fmt.Scan(&n)
	g := make([][]int, n+1)
	for i := 0; i < n; i++ {
		var u,k int
		fmt.Scan(&u)
		fmt.Scan(&k)
		g[u] = make([]int, k)
		for j := 0; j < k; j++ {
			fmt.Scan(&g[u][j])
		}
	}

	d := make([]int, n+1)
	f := make([]int, n+1)
	t := 1
	for i := 1; i <= n; i++ {
		t = dfs(&g, &d, &f, i, t)
	}

	for i := 1; i <= n; i++ {
		fmt.Printf("%d %d %d\n", i, d[i], f[i])
	}
}

func dfs(g *[][]int, d *[]int, f *[]int, id int, t int) int {
	if (*d)[id] > 0 {
		return t
	}
	(*d)[id] = t
	t += 1
	for i := 0; i < len((*g)[id]); i++ {
		t = dfs(g, d, f, (*g)[id][i], t)
	}
	(*f)[id] = t
	return t+1
}

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, tm = 0;
vvi M;
vi D, F, searchStatus;

void dfs(int u) {
	searchStatus[u] = 0;
	D[u] = ++tm;
	REP3(i, 1, n) {
		if (M[u][i] == 0) continue;

		if (searchStatus[i] == -1) {
			dfs(i);
		}
	}
	F[u] = ++tm;
	searchStatus[u] = 1;
}

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

void solve() {
	REP3(i, 1, n) searchStatus[i] = -1;

	REP3(i, 1, n) {
		if (searchStatus[i] == -1) {
			dfs(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);

	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 <iostream>
#include <vector>
#include <list>
#include <cstdlib>

const int MAX_N = 100;

struct Node {
  int v;
  int firstVisitedTime;
  int lastVisitedTime;
  bool visited;
  bool opened;
};

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

  int n = 0;
  std::cin >> n;

  std::vector<std::list<int> *> *graph = new std::vector<std::list<int> *>(n + 1);
  std::vector<struct Node *> *nodes = new std::vector<struct Node *>(n + 1);
  
  for (int i = 1; i <= n; i++) {
    int v = 0;
    std::cin >> v;

    int k = 0;
    std::cin >> k;

    std::list<int> *neighbors = new std::list<int>();

    for (int j = 0; j < k; j++) {
      int a = 0;
      std::cin >> a;

      if (v == j) {
	continue;
      }

      neighbors->push_back(a);
    }

    graph->at(i) = neighbors;

    struct Node *node = (struct Node *) std::malloc(sizeof(struct Node));

    node->v = i;
    node->firstVisitedTime = 0;
    node->lastVisitedTime = 0;
    node->visited = false;
    node->opened = false;
    
    nodes->at(i) = node;
  }
  
  std::list<int> *stack = new std::list<int>();

  
  int start = 1;
  
  stack->push_front(start);
  
  nodes->at(start)->firstVisitedTime = 1;
  nodes->at(start)->lastVisitedTime = 1;

  int count = 0;

  while (!stack->empty()) {
    count++;
    
    int n = stack->front();
    struct Node *node = nodes->at(n);

    if ((node->visited) && (!node->opened)) {
      count--;
    }
    
    if (!node->visited) {
      node->firstVisitedTime = count;
      node->visited = true;
    }
    
    //std::cout << count << " = " << n << std::endl;
    
    if (node->opened) {
      node->lastVisitedTime = count;
       
      stack->pop_front();

      if (stack->empty()) {
	for (std::vector<struct Node *>::iterator iterator = nodes->begin() + 1; iterator != nodes->end(); ++iterator) {
	  struct Node *node = *iterator;

	  if (!node->visited) {
	    nodes->at(node->v)->firstVisitedTime = count;
	    nodes->at(node->v)->lastVisitedTime = count;

	    stack->push_back(node->v);

	    break;
	  }
	}	
      }
      
      continue;
    }
    
    std::list<int> *neighbors = graph->at(n);

    while (!neighbors->empty()) {
      int v = neighbors->front();
      neighbors->pop_front();

      if (!nodes->at(v)->visited) {
	stack->push_front(v);

	break;
      }
    }

    if (neighbors->empty()) {
      node->opened = true;
    }
  }

  for (std::vector<struct Node *>::iterator iterator = nodes->begin() + 1; iterator != nodes->end(); ++iterator) {
    struct Node *node = *iterator;
        
    std::cout << node->v << " " << node->firstVisitedTime << " " << node->lastVisitedTime << std::endl;
  }
  
  return 0;
}

C++: #include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <list>
#include <utility>
#include <ctime>
#define INF 1000000000
#define LINF 9000000000000000000
#define mod 1000000007
 
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rrep(i,n) for(int i=(n);i>=0;i--)
#define REP(i,a,b) for(int i=(a);i<int(b);i++)
#define all(x) (x).begin(),x.end()
#define vector_rsort(x) sort(all(x));reverse(all(x))
#define array_rsort(x,n) sort(x,x+n);reverse(x,x+n);
#define pb push_back
#define mp make_pair
#define MOD(x) (x%(mod))

#define Yes cout<<"Yes"<<endl
#define YES cout<<"YES"<<endl
#define No cout<<"No"<<endl
#define NO cout<<"NO"<<endl
using namespace std;
 
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef pair<int,int> pi;
 
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
bool debug=false;
/*---------------------------------------------------*/

int n,t=1;
int d[105],f[105];
int used[105];
vi g[105];

void init(){
  rep(i,105){
    d[i]=f[i]=INF;
  }
}

void dfs(int now){
  d[now]=min(d[now],t);
  rep(i,g[now].size()){
    if(!used[g[now][i]]){
      used[now]=true;
      t++;
      dfs(g[now][i]);
    }
  }
  t++;
  f[now]=min(f[now],t);
}

int main(){
  int u,k,v;
  cin>>n;
  rep(i,n){
    cin>>u>>k;
    rep(j,k){
      cin>>v;
      g[u].pb(v);
    }
  }
  init();
  REP(i,1,n+1)dfs(i);
  REP(i,1,n+1){
    cout<<i<<" "<<d[i]<<" "<<f[i]<<endl;
  }
  return 0;
}

C++: #include <bits/stdc++.h>
#define W 0
#define B 1
#define G 2
#define rep(i,a) for(i=1;i<=a;i++)
using namespace std;

vector <vector<int> > A;
vector <int> c;
vector <int> d;
vector <int> f;
vector <int> k;

int n,u,t;

void visit(int r) {
    int i;
    c[r] = G;
    d[r] = ++t;
    rep(i,k[r]){
        if(c[A[r][i]] == W) visit(A[r][i]);
    }
    c[r] = B;
    f[r] = ++t;
}

void dfs(void){
    int i;
    rep(i,n) 
        c[i] = W;
    t = 0;
    rep(i,n){
        if(c[i] == W) visit(i);
    }
}

int main(void){
    int i,j;
    cin >> n;
    c.resize(n+1);
    d.resize(n+1);
    f.resize(n+1);
    k.resize(n+1);
    A.resize(n+1);
    rep(i,n) A[i].resize(n+1);
    rep(i,n){
        cin >> u >> k[i];
        rep(j,k[i]){
            cin >> A[i][j];
        }
    }
    dfs();
    rep(i,n){
        cout << i << " " <<d[i] << " "<< f[i] << endl;
    }
    return 0;
}