Go: package main

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

type vertexId int

type vertex struct {
	id vertexId
	firstVisitAt int
	finishVisitAt int
	adjs []vertexId
}

func createVertex(id int, adjsInt []int) vertex {
	adjs := make([]vertexId, len(adjsInt))
	for i := 0; i < len(adjs); i++ {
		adjs[i] = vertexId(adjsInt[i])
	}
	return vertex{
		id: vertexId(id),
		firstVisitAt: 0,
		finishVisitAt: 0,
		adjs: adjs,
	}
}

func (v *vertex) doesAllAdjsVisited(vertices []vertex) bool {
	for _, vId := range v.adjs {
		adj := vertices[vId-1]
		if !adj.isVisited() {
			return false
		}
	}
	return true
}

func (v *vertex) isFirstVisit() bool {
	return v.firstVisitAt == 0
}

func (v *vertex) isVisited() bool {
	return v.firstVisitAt > 0
}

func (v *vertex) nextVertex(vertices []vertex) (vertexId, error) {
	for _, vId := range v.adjs {
		adj := vertices[vId-1]
		if !adj.isVisited() {
			return vId, nil
		}
	}
	return vertexId(-1), fmt.Errorf("illegal")
}

func dfs(currentId vertexId, timestamp int, vertices []vertex) int {
	timestamp = timestamp + 1
	currentVertex := &vertices[currentId-1]
	if currentVertex.isFirstVisit() {
		currentVertex.firstVisitAt = timestamp
	}
	for !currentVertex.doesAllAdjsVisited(vertices) {
		nextVertexId, _ := currentVertex.nextVertex(vertices)
		timestamp = dfs(nextVertexId, timestamp, vertices)
	}
	timestamp = timestamp + 1
	currentVertex.finishVisitAt = timestamp
	return timestamp
}

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

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

	vertices := make([]vertex, n)
	for i := 0; i < n; i++ {
		id, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjN, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		adjs := make([]int, adjN)
		for j := 0; j < adjN; j++ {
			adjId, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			adjs[j] = adjId
		}
		vertices[i] = createVertex(id, adjs)
	}

	dfs(vertexId(1), 0, vertices)

	for i := 0; i < n; i++ {
		fmt.Printf("%d %d %d\n", vertices[i].id, vertices[i].firstVisitAt, vertices[i].finishVisitAt)
	}
}

func nextText(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

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

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

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP0(i,n) for(int i=0, i##_len=(n); i<i##_len; ++i)
#define REP1(i,n) for(int i=1, i##_len=(n); i<=i##_len; ++i)
#define RREP0(i,n) for(int i=n-1; i>=0; --i)
#define RREP1(i,n) for(int i=n; i>=1; --i)

#define SORT(c) sort((c).begin(),(c).end())
#define whole(f,x,...) ([&](decltype((x)) whole) { return (f)(begin(whole), end(whole), ## __VA_ARGS__); })(x)
#define PB push_back
#define MP make_pair
#define SZ(a) int((a).size())
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define CLR(a) memset((a), 0 ,sizeof(a))
#define N 100

inline int toInt(string s) {int v; istringstream sin(s);sin>>v;return v;}
template<class T> inline string toString(T x) {ostringstream sout;sout<<x;return sout.str();}

typedef long long LL;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;

const int INTINF = 2147483647;
const LL LLINF = 9223372036854775807;
const double EPS = 1e-10;
const double PI  = acos(-1.0);

int gcd(int a,int b){return b?gcd(b,a%b):a;}
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int M[N][N];
int n, tt, d[N], f[N];
int color[N]; //-1:unvisited, 0:visited, 1:finished
int nt[N];

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


int next(int u){
  FOR(v, nt[u], n){
    nt[u]=v+1;
    if (M[u][v]) return v; // where v is first next_to_u
  }
  return -1;
}


void dfs_visit(int r){
  REP0(i,n) nt[i]=0;

  stack<int> S;
  S.push(r);
  color[r] = GRAY;
  d[r] = ++tt;

  while (!S.empty()) {
    int u=S.top();
    int v=next(u);
    if (v!=-1) {
      if (color[v]==WHITE) {
        color[v]=GRAY;
        d[v]=++tt;
        S.push(v);  //次のループで取り出されるu
      }
    }else{ //隣接未探索なし
      S.pop();
      color[u]=BLACK;
      f[u]=++tt;
    }
  }

}


void dfs(){
  REP0(i,n){
    color[i]=WHITE;
    nt[i]=0;
  }
  tt=0;
  REP0(i,n) if (color[i]==WHITE) dfs_visit(i);
  REP0(i,n) std::cout << i+1 << " " << d[i] << " " << f[i] << '\n';
}


void input(int n){
  int v1, v2, d;
  REP0(i,n) { REP0(j,n) M[i][j]=0; }
  REP0(i,n){
    std::cin >> v1 >> d;
    color[v1-1]=-1;
    REP0(j,d){
      std::cin >> v2; M[v1-1][v2-1]=1;
    }
  }
}


int main(int argc, char const *argv[]) {
  cin.tie(0); ios::sync_with_stdio(false);
  std::cin >> n;
  input(n);
  dfs();
  return 0;
}

C++: #include <cstdio>
int dt[101][101];
int d[101], f[101];

int n;
int t=2;
void dfs(int s){
	for(int i=1;i<=n;i++){
		if(dt[s][i]&&d[i]==0){
			d[i]=t;
			t++;
			dfs(i);
		}
	}
	f[s]=t++;
}
int main(){
	int fi, v, g;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d %d",&fi,&v);
		for(int j=1;j<=v;j++){
			scanf("%d",&g);
			dt[fi][g]=1;
		}
	}
	d[1]=1;
	dfs(1);
	for(int i=1;i<=n;i++){
		printf("%d %d %d\n",i,d[i],f[i]);
	}
	return 0;
}

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

using namespace std;
typedef long long ll;
//typedef unsigned long long ll;

//#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep(i, n) for (ll i = 0; i < (n); ++i)
//#define sz(x) ll(x.size())
//typedef pair<ll, int> P;
//typedef pair<ll, ll> P;
const double INF = 1e10;
//const ll INF = LONG_LONG_MAX / 10;
//const ll INF = 1e15;
const ll MINF = LONG_LONG_MIN;
//const int INF = INT_MAX / 10;
#define cmin(x, y) x = min(x, y)
#define cmax(x, y) x = max(x, y)

bool contain(set<int> &s, int a) { return s.find(a) != s.end(); }

//ifstream myfile("C:\\Users\\riku\\Downloads\\0_00.txt");
//ofstream outfile("log.txt");
//outfile << setw(6) << setfill('0') << prefecture << setw(6) << setfill('0') << rank << endl;
// std::cout << std::bitset<8>(9);

typedef pair<double, double> P;

void print_line(vector<int> &line) {
    if (line.size() == 0ll) {
        cout << endl;
        return;
    }
    for (ll i = 0; i < line.size(); i++) {
        cout << line[i];
        if (i == line.size() - 1) cout << endl;
        else cout << ' ';
    }
}


typedef priority_queue<long long, vector<long long>, greater<long long>> PQ_ASK;
const int mod = 1000000007;

int dfs(int from, int turn, vector<vector<int>> &tos, set<int> &used, vector<vector<int>> &ans) {
    used.erase(from);
    ans[from][1] = turn;
    for (int to : tos[from]) {
        if (contain(used, to)) {
            turn = dfs(to, turn + 1, tos, used, ans);
        }
    }
    turn++;
    ans[from][2] = turn;
    return turn;
}

int main() {
    int n;
    cin >> n;
    vector<vector<int>> tos(n);
    rep(i, n) {
        int j, k;
        cin >> j >> k;
        j--;
        rep(l, k) {
            int m;
            cin >> m;
            m--;
            tos[j].push_back(m);
        }
    }

    vector<vector<int>> ans(n, vector<int>(3, 0));

    rep(i, n) sort(tos[i].begin(), tos[i].end());
    set<int> used;
    rep(i, n) used.insert(i);
    int turn = 0;
    while (!used.empty()) turn = dfs(*used.begin(), turn + 1, tos, used, ans);

    rep(i, n) ans[i][0] = i + 1;
    rep(i, n) print_line(ans[i]);
}