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<iostream>
#include<cstdio>
#define N 100
#define  GRAY 1
#define BLACK 2
using namespace std;
int n,M[N][N];
int color[N],d[N],f[N],tt;
void dfs_visit(int u)
{
  int v;
  color[u] = GRAY;
  d[u] = ++tt;
  for(v = 0;v<n;v++)
  {  if(M[u][v] == 0)
     continue;
  if(color[v] == 0)
    {
      dfs_visit(v);
    }
}
  color[u] = BLACK;
  f[u] == ++tt;
}
void dfs()
{
  int u;
  for(u = 0;u<n;u++)
     color[u] = 0;
  tt = 0;
  for(u = 0;u<n;u++)
  {
    if(color[u] == 0) dfs_visit(u);
  }
  for(u = 0;u<n;u++)
  {
    printf("%d %d %d\n",u+1,d[u],f[u]);
  }
}
int main ()
{
  int u,v,k,i,j;
  scanf("%d",&n);
  for( i = 0;i<n;i++)
    for( j = 0;j<n;j++)
        M[i][j] = 0;
  for( i =0;i<n;i++)
   {
     scanf("%d %d",&n,&k);
     u--;
     for( j = 0;j<n;j++)
       {
         scanf("%d",&v);
         v--;
         M[u][v] = 1;
       }
   }
   dfs();
  return  0 ;
}

C++: #include<stdio.h>
#include<algorithm>
#include<stack>
#include<string.h>
using namespace std;
#define INFTY 2000000001
#define MAX 101
#define WHITE 0
#define GRAY 1
#define BLACK 2

int n = 0;
int adl[MAX][MAX], deg[MAX];
int adm[MAX][MAX];
int color[MAX];
int d[MAX][2];
stack<int> depth;


void dfs() {
  int time = 1;
  for ( int i = 0; i < n; i++ ) {
    color[i] = WHITE;
  }
  depth.push(0);
  color[0] = GRAY;
  d[0][0] = time++;

  while (!depth.empty()) {
    int top = depth.top();

    int next;
    for (int i = 0; i < n; i++) {
      next = i;
      if (adm[top][i] == 1 && color[i] == WHITE) {
        depth.push(i);
        d[i][0] = time++;

        color[i] = GRAY;
        break;
      }
      next = n;
    }

    if (next == n) {
      color[top] = BLACK;
      d[top][1] = time++;
      depth.pop();
    }

    if (depth.empty()) {
      for (int i = 0; i < n; i++) {
        if (color[i] == WHITE) {
          depth.push(i);
          color[i] = GRAY;
          d[i][0] = time++;
        }
      }
    }
  }
}

int main() {
  scanf("%d", &n);
  for ( int i = 0; i < n; i++ ) {
    for ( int j = 0; j < n; j++ ) {
      adm[i][j] = 0;
    }
  }
  for ( int i = 0; i < n; i++ ) {
    int num;
    scanf("%d", &num);
    num--;
    scanf("%d", &deg[num]);
    for ( int j = 0; j < deg[num]; j++) {
      scanf("%d", &adl[num][j]);
      adl[num][j]--;
      adm[num][adl[num][j]] = 1;
    }
  }

  dfs();

  for ( int i = 0; i < n; i++ ) {
    printf("%d %d %d\n", i+1, d[i][0], d[i][1]);
  }



  return 0;
}

C++: #include <cstdio>
#include <vector>
#include <algorithm>

#define rep(i, n) for(int i = 0; i < (n); ++i)

using namespace std;

int n;
vector<int> g[100];
int t;
int p[100];
int q[100];

void dfs(int i){
	p[i] = t++;
	rep(j, g[i].size()){
		int v = g[i][j];
		if(!p[v]){
			dfs(v);
		}
	}
	q[i] = t++;
}

int main(){
	scanf("%d", &n);
	rep(i, n){
		int u, k;
		scanf("%d%d", &u, &k);
		rep(j, k){
			int v;
			scanf("%d", &v);
			g[u - 1].push_back(v - 1);
		}
	}
	rep(i, n){
		if(!p[i]){
			t = 1;
			dfs(i);
		}
	}
	rep(i, n){
		printf("%d %d %d\n", i + 1, p[i], q[i]);
	}
	return 0;
}

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

#define ll long long
#define vvi vector<vector<int>>
#define vec vector
#define pq priority_queue
#define all(v) (v).begin(), (v).end()
#define uniqueV(x) sort(x.begin(), x.end()); x.erase(unique(x.begin(), x.end()), x.end());
#define rep(i, n) for (int (i) = (0); (i) < (n); ++(i))
#define repp(i, m, n) for (int (i) = (m); (i) < (n); ++(i))
#define debug(x) cerr << #x << ": " << x << endl;
#define debug2(x, y) cerr<<"("<<#x<<", "<<#y<<") = "<<"("<<x<<", "<<y<<")"<<endl;
#define debug3(x, y, z) cerr<<"("<<#x<<", "<<#y<<", "<<#z<<") = "<<"("<<x<<", "<<y<<", "<<z<<")"<<endl;
#define debugB(x, y) cerr<<#x<<": "<<bitset<y>(x) << endl;
#define line() cerr << "---------------" << endl;

const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, -1, 1};

template<typename T>
void printA(vector<T> &printArray, char between = ' ') {
   int paSize = printArray.size();
   for (int i = 0; i < paSize; i++) { cerr << printArray[i] << between;}
   if (between != '\n') {cerr << endl;}
}

// ------------------------------------------------------------------------------------------

int N;
vector<vector<int>> G;
int d[111], f[111];
int turn;

void dfs(int from) {
   turn++;
   for (int to : G[from]) {
      if (d[to] == 0) {
         d[to] = turn;
         dfs(to);
         turn++;
      }
   }
   f[from] = turn;
}

int main() {
   cin >> N;
   G = vector<vector<int>>(N);
   rep (i, N) {
      int u, k; cin >> u >> k;
      u--;
      rep (j, k) {
         int a; cin >> a;
         a--;
         G[u].push_back(a);
      }
   }

   rep (i, N) {
      sort(G[i].begin(), G[i].end());
   }

   // f[0] = dfs(0, 1);
   d[0] = 1;
   turn = 1;
   dfs(0);

   rep (i, N) {
      printf("%d %d %d\n", i+1, d[i], f[i]);
   }

   return 0;
}

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

using namespace std;

int n, m;
const int N = 110;
vector<int> G[N];
int d[N], f[N];
int timestamp = 1;

void dfs(int u) {
    d[u] = timestamp++;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (d[v] > 0) continue;
        dfs(v);
    }
    f[u] = timestamp++;
}

int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        int u, k;
        cin >> u >> k;
        int v;
        for (int j = 0; j < k; j++) {
            cin >> v;
            if (u != v)
            G[u].push_back(v);
        }
    }

    for (int u = 1; u <= n; u++) {
        if (d[u] == 0) dfs(u);
    }

    for (int u = 1; u <= n; u++) {
        cout << u << " " << d[u] << " " << f[u] << endl; 
    }

    return 0;
}