Go: package main

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

/***************************************************************
stackによる深さ優先探索を実装する。
***************************************************************/

const (
	N     = 100
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

var (
	n            int
	Adj          [N][N]int
	statusColor  [N]int
	discoverTime [N]int
	finishTime   [N]int
	clock        int
	nt           [N]int
)

/***************************************************************
Stackの定義:
- field
	container: ノードの格納されたスライス
	sp: スタックポインタ
- method
	size(): スタックに積まれているノードの個数を返す
	top(): スタックの一番上に積まれているノードを返す
	isEmpty(): スタックが空かどうかを返す
	pop(): スタックの要素をポップし削除する
	push(): スタックに要素を積む
***************************************************************/

type Stack struct {
	container []int
	sp        int
}

func (s *Stack) size() int {
	return len(s.container)
}

func (s *Stack) top() int {
	return s.container[s.sp]
}

func (s *Stack) isEmpty() bool {
	return s.sp == 0
}

func (s *Stack) pop() int {
	_pop := func() {
		s.container = s.container[:len(s.container)-1]
	}
	defer _pop()
	if s.isEmpty() {
		panic("There is no elements in stack!")
	}
	s.sp--
	return s.container[s.sp]
}

func (s *Stack) push(n int) {
	s.sp++
	s.container[s.sp] = n
}

func next(u int) int {
	for v := nt[u]; v < n; v++ {
		nt[u] = v + 1
		if Adj[u][v] == 1 {
			return v
		}
	}
	return -1
}

func _DFS(target int) {
	for i := 0; i < n; i++ {
		nt[i] = 0
	}
	stack := new(Stack)
	stack.container = make([]int, N+1)
	stack.push(target)
	statusColor[target] = GRAY
	clock++
	discoverTime[target] = clock
	for !stack.isEmpty() {
		u := stack.top()
		v := next(u)
		if v != -1 {
			if statusColor[v] == WHITE {
				statusColor[v] = GRAY
				clock++
				discoverTime[v] = clock
				stack.push(v)
			}
		} else {
			stack.pop()
			statusColor[u] = BLACK
			clock++
			finishTime[u] = clock
		}
	}
}

func DFS() {
	for i := 0; i < n; i++ {
		statusColor[i] = WHITE
		nt[i] = 0
	}
	clock = 0
	for i := 0; i < n; i++ {
		if statusColor[i] == WHITE {
			_DFS(i)
		}
	}
	for i := 0; i < n; i++ {
		fmt.Printf("%d %d %d\n", i+1, discoverTime[i], finishTime[i])
	}
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	scanner.Scan()
	n, _ = strconv.Atoi(scanner.Text())
	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			Adj[i][j] = 0
		}
	}
	for i := 0; i < n; i++ {
		scanner.Scan()
		u, _ := strconv.Atoi(scanner.Text())
		scanner.Scan()
		k, _ := strconv.Atoi(scanner.Text())
		u--
		for j := 0; j < k; j++ {
			scanner.Scan()
			v, _ := strconv.Atoi(scanner.Text())
			v--
			Adj[u][v] = 1
		}
	}

	DFS()
}

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;
}