Go: package main

import "fmt"

type node struct {
	id, d, v int
	adj      []node
}

var n int
var seen []bool
var graph []node

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func dfs(v, t int) int {
	// fmt.Printf("dfs(v %d, t %d) en:\n", v, t)
	seen[v] = true
	graph[v].v = t
	tt := t
	for _, vv := range graph[v].adj {
		if !seen[vv.id] {
			tt = max(tt, dfs(vv.id, tt+1))
		}
	}
	graph[v].d = tt + 1
	// fmt.Printf("dfs(v %d, t %d) ex: d %d\n", v, t, graph[v].d)
	return graph[v].d
}

func main() {
	fmt.Scan(&n)
	graph = make([]node, n+1)
	for i := 1; i <= n; i++ {
		var u, k, v int
		fmt.Scan(&u, &k)
		graph[u].id = u
		// 頂点uはk個の隣接頂点を持っている
		for j := 0; j < k; j++ {
			fmt.Scan(&v)
			var t node
			t.id = v
			graph[u].adj = append(graph[u].adj, t)
		}
	}
	// fmt.Println("n", n, "graph", graph)
	seen = make([]bool, n+1)
	// t := dfs(1, 1)
	v, t := 1, 1
	done := false
	for !done {
		tt := dfs(v, t)
		done = true
		for i := range seen {
			if !seen[i] {
				done = false
				v = graph[i].id
				t = tt
				break
			}
		}
	}
	for i := 1; i <= n; i++ {
		fmt.Printf("%d %d %d\n", i, graph[i].v, graph[i].d)
	}
}

C++: #define _CRT_SECURE_NO_WARNINGS

#include<iostream>
#include<functional>
#include<algorithm>
#include<stack>
#include<queue>
#include<iomanip>
#include<set>
#include<map>
#include<utility>
#include<string>
#include<vector>

using namespace std;

#define LL long long
const int dx[4] = { 1,-1,0,0 };
const int dy[4] = { 0,0,1,-1 };
bool OOA(int x,int y,int H,int W){return (0<=x&&x<H)&&(0<=y&&y<W);}

struct Graph{
	int V,E,t;
	vector<int>cost;
	vector<int>d;
	vector<int>f;
	vector<bool>vzt;
	vector<vector<int>>adj;
	void init(int dflt){//dflt!=0
		t=1;
		adj=vector<vector<int>>(V+1);
		cost = vector<int>(V + 1, dflt);
		d = vector<int>(V + 1, dflt);
		f = vector<int>(V + 1, dflt);
		vzt=vector<bool>(V+1,false);
	}

	void bfs(int s, int scost){
		queue<pair<int,int>>q;
		q.push({scost,s});
		vzt[s]=true;
		cost[s]=0;
		while(!q.empty()){
			auto top=q.front();
			q.pop();
			int cst=top.first,now=top.second;
			for(int i=0;i<adj[now].size();i++){
				if(!vzt[adj[now][i]]){
					vzt[adj[now][i]]=true;
					cost[adj[now][i]]=cost[now]+1;
					q.push({cost[adj[now][i]],adj[now][i]});
				}
			}
		}
	}

	void dfs(int now){
		if(d[now]==-1){d[now]=t;t++;}
		else return;
		for(int i=0;i<adj[now].size();i++)dfs(adj[now][i]);
		if(f[now]==-1){f[now]=t;t++;}
		return;
	}
};

int n;
Graph G;

int main() {
	cin>>n;
	G.V=n;
	G.init(-1);
	for(int i=0;i<n;i++){
		int u,k;
		cin>>u>>k;
		for(int j=0;j<k;j++){
			int v;
			cin>>v;
			G.adj[u].push_back(v);
		}
	}
	for(int i=1;i<=n;i++)G.dfs(i);
	for(int i=1;i<=G.V;i++)cout<<i<<" "<<G.d[i]<<" "<<G.f[i]<<endl;
	return 0;
}

C++: #include<iostream>
int s[100]={0},f[100]={0},B[100][100]={0},A[100]={0},d[100],c[100]={0},cnt=1,tmp;
bool con(int A[],int n){
	for(int i=0;i<n;i++){
		if(A[i]==0){
			tmp=i;
			return true;
		}
	}
	return false;
}
void search(int v){
  A[v]=1;
  s[v]=cnt++;
  for(int i=0;i<d[v];i++){
    if(A[B[v][i]]==0){
      search(B[v][i]);
    }
  }
  f[v]=cnt++;
}
int main(){
  int n,num,flag;
  std::cin>>n;
  for(int i=0;i<n;i++){
    std::cin>>num>>d[i];
    for(int j=0;j<d[i];j++){
      std::cin>>flag;
      B[num-1][j]=flag-1;
    }
  }
  search(0);
	while(con(A,n)){
		search(tmp);
	}
  for(int i=0;i<n;i++){
    std::cout<<i+1<<" "<<s[i]<<" "<<f[i]<<"\n";
  }
  return 0;
}

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

using namespace std;

#define ll long long
typedef complex<double> P;

int main() {
  int n; cin >> n;
  int adj[n][n] = {};

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

  int d[n] = {};
  int f[n] = {};
  int t = 1;

  stack<int> st;
  st.push(0);

  while (!st.empty()) {
    int v = st.top();

    if(d[v] == 0) {
      d[v] = t;
    }

    for (int i = 0; i < n; i++) {
      if(adj[v][i] == 1 && d[i] == 0) {
        st.push(i);
        break;
      }
    }

    if(st.top() == v) {
      f[v] = t+1;
      st.pop();
    }

    t++;
  }

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

}

C++: #define _USE_MATH_DEFINES
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <clocale>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

#define IOS ios::sync_with_stdio(false); cin.tie(0);
#define FOR(i, s, n) for(int i = (s), i##_len=(n); i < i##_len; ++i)
#define FORS(i, s, n) for(int i = (s), i##_len=(n); i <= i##_len; ++i)
#define VFOR(i, s, n) for(int i = (s); i < (n); ++i)
#define VFORS(i, s, n) for(int i = (s); i <= (n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define REPS(i, n) FORS(i, 0, n)
#define VREP(i, n) VFOR(i, 0, n)
#define VREPS(i, n) VFORS(i, 0, n)
#define RFOR(i, s, n) for(int i = (s), i##_len=(n); i >= i##_len; --i)
#define RFORS(i, s, n) for(int i = (s), i##_len=(n); i > i##_len; --i)
#define RREP(i, n) RFOR(i, n, 0)
#define RREPS(i, n) RFORS(i, n, 0)
#define ALL(v) (v).begin(), (v).end()
#define SORT(v) sort(ALL(v))
#define RSORT(v) sort(ALL(v), greater<decltype(v[0])>())
#define SZ(x) ((int)(x).size())
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define BIT(n) (1LL<<(n))
#define UNIQUE(v) v.erase(unique(ALL(v)), v.end())

using ll = long long;
using Pi_i = pair<int, int>;
using VB = vector<bool>;
using VC = vector<char>;
using VD = vector<double>;
using VI = vector<int>;
using VLL = vector<ll>;
using VS = vector<string>;
using VSH = vector<short>;

const int MOD = 1000000007;
const int INF = 1000000000;
const int NIL = -1;

template<class T, class S>
bool chmax(T &a, const S &b){
    if(a < b){
        a = b; return true;
    }
    return false;
}
template<class T, class S>
bool chmin(T &a, const S &b){
    if(b < a){
        a = b; return true;
    }
    return false;
}



VI visitedTime, allSearchedTime;
vector<VI> edge;
int n, t;

void dfs(int u){
    visitedTime[u] = ++t;
    for(auto v: edge[u]){
        if(!visitedTime[v]) dfs(v);
    }
    allSearchedTime[u] = ++t;
}

void solve(){
    t = 0;
    REP(u, n)
        if(!visitedTime[u]) dfs(u);
    
    REP(u, n)
        cout << u+1 << " " << visitedTime[u] << " " << allSearchedTime[u] << "\n";
}

int main(){
    cin >> n;
    visitedTime.resize(n, 0);
    allSearchedTime.resize(n, 0);
    edge.resize(n);
    REP(i, n){
        int u; cin >> u; --u;
        int k; cin >> k;
        REP(j, k){
            int v; cin >> v; --v;
            edge[u].PB(v);
        }
    }

    solve();
    return 0;
}

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

int a[100][100],n;
int d[100],f[100],c[100],tt;
int nt[100];

int next(int u){
  for(int i=nt[u];i<n;i++){
    nt[u]=i+1;
    if(a[u][i]) return i;
  }
  return -1;
}

void dfs_v(int r){
  for(int i=0;i<n;i++) nt[i]=0;
  stack<int> s;
  s.push(r);
  c[r]=1;
  d[r]=++tt;
  while(!s.empty()){
    int u=s.top();
    int v=next(u);
    if(v!=-1){
      if(c[v]==0){
	c[v]=1;
	d[v]=++tt;
	s.push(v);
      }
    }else{
      s.pop();
      c[u]=2;
      f[u]=++tt;
    }
  }
}

void dfs(){
  for(int i=0;i<n;i++){
    c[i]=0;
    nt[i]=0;
  }
  tt=0;
  for(int i=0;i<n;i++){
    if(c[i]==0) dfs_v(i);
  }
  for(int i=0;i<n;i++){
    cout<<i+1<<" "<<d[i]<<" "<<f[i]<<endl;
  }
}


  
int main(){
  int u,k,v;
  cin>>n;
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++) a[i][j]=0;
  }
  for(int i=0;i<n;i++){
    cin>>u>>k;
    u--;
    for(int j=0;j<k;j++){
      cin>>v;
      v--;
      a[u][v]=1;
    }
  }
  dfs();
  return 0;
}