Go: package main

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

var scanner = bufio.NewScanner(os.Stdin)

func nextString() string {
	scanner.Scan()
	return scanner.Text()
}

func nextInt() int {
	n, err := strconv.Atoi(nextString())
	if err != nil {
		fmt.Printf("strconv.Atoi failed: %v\n", err)
	}
	return n
}

var infty = 1000000000

type nodeKey int

type DirectedGraphNode struct {
	key       nodeKey
	adjacents []*DirectedGraphNode
	visited   bool
	d         int
	f         int
	parent    *DirectedGraphNode
}

type DirectedGraph struct {
	nodes []*DirectedGraphNode
}

func (g *DirectedGraph) setAdjacency(l, r nodeKey) {
	g.nodes[l].adjacents = append(g.nodes[l].adjacents, g.nodes[r])
}

func newDirectedGraph(nNodes int) *DirectedGraph {
	graph := DirectedGraph{}
	graph.nodes = make([]*DirectedGraphNode, nNodes)
	for iNodes := 0; iNodes < nNodes; iNodes++ {
		graph.nodes[iNodes] = &DirectedGraphNode{}
		graph.nodes[iNodes].key = nodeKey(iNodes)

		graph.nodes[iNodes].visited = false
		graph.nodes[iNodes].d = infty
		graph.nodes[iNodes].f = infty
		graph.nodes[iNodes].parent = nil
	}
	return &graph
}

type QueueEntry struct {
	node *DirectedGraphNode
	next *QueueEntry
}

type Queue struct {
	head, tail *QueueEntry
}

func (q *Queue) enqueue(node *DirectedGraphNode) {
	entry := QueueEntry{}
	entry.node = node

	if q.tail == nil {
		q.head = &entry
		q.tail = &entry
		return
	}

	q.tail.next = &entry
	q.tail = q.tail.next
}

func (q *Queue) dequeue() *QueueEntry {
	if q.head == nil {
		return nil
	}
	poped := q.head
	q.head = q.head.next
	if q.head == nil {
		q.tail = nil
	}
	return poped
}

func (q *Queue) isEmpty() bool {
	return q.head == nil
}

var time = 0

func fillDistancesByDepthFirstSearch(g *DirectedGraph) {
	for _, u := range g.nodes[1:] {
		if !u.visited {
			dfsVisit(g, u)
		}
	}
}

func dfsVisit(g *DirectedGraph, u *DirectedGraphNode) {
	time++
	u.d = time

	u.visited = true
	for _, v := range u.adjacents {
		if !v.visited {
			v.parent = u
			dfsVisit(g, v)
		}
	}
	time++
	u.f = time
}

func main() {
	scanner.Split(bufio.ScanWords)

	nNodes := nextInt()
	g := newDirectedGraph(nNodes + 1)

	for iNode := 0; iNode < nNodes; iNode++ {
		nodeKeyLeft := nodeKey(nextInt())
		nAdj := nextInt()
		for iAdj := 0; iAdj < nAdj; iAdj++ {
			nodeKeyRight := nodeKey(nextInt())
			g.setAdjacency(nodeKeyLeft, nodeKeyRight)
		}
	}

	fillDistancesByDepthFirstSearch(g)

	for iNode := 1; iNode <= nNodes; iNode++ {
		node := g.nodes[iNode]
		fmt.Println(node.key, node.d, node.f)
	}
}

C++: #include <iostream>
using namespace std;

int r[101][101];
int d[101], f[101], num, visit[100]={0}, p=1;

void dfs(int n){
    if(visit[n]!=1){
        visit[n] = 1;
        d[n] = p++;
        for(int i=1; i<num+1; i++)
            if(r[n][i]==1) dfs(i);
        f[n] = p++;
    }
}

int main(void){
    int u, k, v;
    cin >> num;
    for(int i=0; i<num; i++){
        cin >> u >> k;
        for(int j=0; j<k; j++){
            cin >> v;
            r[u][v]=1;
        }
    }
    for(int i=1; i<num+1; i++){
        if(visit[i]!=1) dfs(i);
    }
    for(int i=1; i<num+1; i++)
        cout << i << " " << d[i] << " " << f[i] << endl;
    return 0;
}

C++: #include <iostream>
#include <algorithm>
 
using namespace std;
 
typedef struct{
  int begin;
  int end;
  bool f;
}fint;
fint T[101];
 
int times = 1;
int n;
int graph[101][101];
 
void bfs(int now){
 
  T[now].f = true;
  T[now].begin = times++;
 
  for( int i = 1 ; i <= n; i++ ){
    if( graph[now][i] == 1 && !T[i].f ) bfs(i);
  }
  T[now].end = times++;
 
}
 
int main(void){
 
  int s,t,u;
  cin >> n;
  for( int i = 0 ; i < n ; i++ ){
    cin >> s >> t;
    for( int j = 1 ; j <= t ; j++ ){
      cin >> u;
      graph[s][u] = 1;
    }
  }
  for( int i = 1 ; i <= n ; i++ ){
    T[i].begin = 0;
    T[i].end = 0;
    T[i].f = false;
  }
  for( int i = 1 ; i <= n ; i++ ){
    if( !T[i].f ) bfs(i);
  }
 
  for( int i = 1 ; i <= n ; i++ ){
    cout << i << " " << T[i].begin << " " << T[i].end << endl;
  }
 
 
  return 0;
}

C++: #include <iostream>
using namespace std;

typedef pair<int, int> edge;

int vernum[101];
edge path[101][101];
int n;

edge found[101];

int t=0;
void dfs(int v){
    t++;
    found[v].first = t;
    int i=0;
    while(1){
        if(!path[v][i].first)
            break;
        if(!found[path[v][i].second].first){
            dfs(path[v][i].second);
        }
        i++;
    }
    t++;
    found[v].second = t;
}

int main() {
    int i, j;
    ios_base::sync_with_stdio(0);
    
    int e, v;
    cin >> n;
    
    for(i=1; i<=n; i++){
        cin >> vernum[i];
        cin >> e;
        for(j=0; j<e; j++){
            cin >> v;
            path[i][j] = make_pair(i, v);
        }
    }
    
    for(i=1; i<=n; i++){
        if(!found[i].first)
            dfs(i);
    }
    
    for(i=1; i<=n; i++){
        cout << vernum[i] << " " << found[i].first << " " << found[i].second << endl;
    }
    
    
    return 0;
}

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

int g[105][105],b[105],f[105],cnt=1,n,is[105];

void dfs(int v)
{
    is[v]=1;
    b[v]=cnt++;
    for(int i=1;i<=n;i++){
        if(i==v) continue;
        if(g[v][i]&&!is[i]) dfs(i);
    }
    f[v]=cnt++;
}

int main()
{
    int v1,d,v2;
    cin>>n;
    memset(g,0,sizeof g);
    memset(is,0,sizeof is);
    for(int i=0;i<n;i++){
        cin>>v1>>d;
        for(int i=0;i<d;i++){
            cin>>v2;
            g[v1][v2]=1;
        }
    }
    dfs(1);
    for(int i=1;i<=n;i++){
        cout<<i<<" "<<b[i]<<" "<<f[i];
        if(i!=n) cout<<endl;
    }
    return 0;
}

C++: #include <bits/stdc++.h>
#define ll long long
#define INF 999999999
#define MOD 1000000007

using namespace std;

typedef pair<int,int>P;

struct edge{
	int from;
	int to;
};

const int MAX_N = 100;

vector<edge> G[MAX_N];
bool flag[MAX_N];
P res[MAX_N];
int t = 1;

void dfs(int x)
{
	res[x].first = t++;
	flag[x] = true;
	for(int i=0;i<G[x].size();i++){
		edge e = G[x][i];
		if(!flag[e.to]){
			dfs(e.to);
		}
	}
	res[x].second = t++;
}

int main()
{
	int n;
	cin >> n;
	for(int i=0;i<n;i++){
		int id,m;
		cin >> id;
		cin >> m;
		for(int j=0;j<m;j++){
			edge e;
			int end;
			cin >> end;
			e.from = id-1;
			e.to = end-1;
			G[id-1].push_back(e);
		}
	}
	fill(flag,flag+n,false);
	int time=0;
	for(int i=0;i<n;i++){
		if(!flag[i]){
			dfs(i);
		}
	}		
	for(int i=0;i<n;i++){
		cout << i+1 << " " << res[i].first << " " << res[i].second << "\n";
	}
}

C++: #include <cstdio>
#include <utility>
#include <vector>
#define rep(i,a) for(int i=0;i<(a);++i)

int n;
std::vector<std::vector<int> > G;
std::vector<bool> used;
std::vector<std::pair<int, int> > res;
int tim = 1;

void dfs( int v )
{
  used[v] = true;
  res[v].first = tim++;

  for( int u : G[v] ) if( !used[u] )
    dfs( u );

  res[v].second = tim++;

  return;
}

int main()
{
  scanf( "%d", &n );
  G.resize( n );
  used.resize( n );
  res.resize( n );

  rep( i, n )
  {
    int u, k;
    scanf( "%d%d", &u, &k );

    rep( j, k )
    {
      int v;
      scanf( "%d", &v );
      G[i].push_back( v-1 );
    }
  }

  rep( i, n ) if( !used[i] )
    dfs( i );

  rep( i, n )
    printf( "%d %d %d\n", i+1, res[i].first, res[i].second );

  return 0;
}