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 <queue>
#include <vector>
#include <algorithm>

using namespace std;

int curTime = 1;
void dfs(int cur, const vector<vector<bool> >& a, vector<int>& d, vector<int>& f, vector<bool>& visited){
  visited[cur] = true;
  d[cur] = curTime;
  curTime++;
  // cerr << "visiting [" << cur << "], time = " << curTime << endl;

  for(int dst = 1; dst <= a.size(); dst++){
    if(a[cur][dst] && !visited[dst]) {// cur????????¶??????????????????????????????
      dfs(dst, a, d, f, visited);
    }
  }
  f[cur] = curTime;
  curTime++;
  return;
}

int main(){
  int n;
  cin >> n;
  vector<vector<bool> > a(n+1, vector<bool>(n+1, false));
  for(int i = 1; i <= n; i++){
    int u;
    cin >> u;
    int k;
    cin >> k;
    for(int j = 0; j < k; j++){
      int v;
      cin >> v;
      a[i][v] = true;
    }
  }

  vector<bool> visited(n+1, false);
  vector<int> d(n+1), f(n+1);

  dfs(1, a, d, f, visited);

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

C++: #include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> F[102];
int start[102]={0},END[102]={0};
bool visit[102]={0};
int Count=0;
void dfs(int now){
	start[now]=Count++;
	visit[now]=true;
	int len=F[now].size();
	for(int i=0;i<len;i++){
		int p=F[now][i];
		if(visit[p]==false){
		     dfs(p);
		}
	}
	END[now]=Count++;
}
int main() {
	int n;
    cin>>n;
    for (int i=0;i<n;i++) {
            int s,num;
            cin>>s>>num;
            s--;
            for (int j=0;j<num;j++) {
                int e;
                cin>>e;
                e--;
				if(e!=s){
					F[s].push_back(e);
				}
            }
        }
        for (int i=0;i<n;i++){
			if(visit[i]==false){
				dfs(i);
			}
        }      
        for (int i = 0; i < n;i++) {
            cout<<i+1<<" "<<start[i]+1<<" "<<END[i]+1<<endl;
        }
    return 0;
}

C++: #include<iostream>
#include<vector>
using namespace std;
vector<vector<int>> G(100);
vector<pair<int,int>> D(100);
bool visited[100];
int elapse = 1;
void dfs(int x){
    if(visited[x]) return;
    visited[x] = true;
    D[x].first = elapse;
    elapse++;
    for(auto &a:G[x]) dfs(a);
    D[x].second = elapse;
    elapse++;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N;
    cin>>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;
            G[u-1].push_back(--v);
        }
    }
    for(int i=0;i<N;++i) dfs(i);
    for(int i=0;i<N;++i) cout<<i+1<<' '<<D[i].first<<' '<<D[i].second<<endl;
}

C++: #include <bits/stdc++.h>
#include<algorithm>
#define int long long
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)


#define INF 1000000000000
int n;
vector<int>d(101);
vector<int>f(101);
vector<vector<int>>g(101,vector<int>(0));
int tim=1;
void dfs(int x){
      if(!d[x]){d[x]=tim;tim++;}
      if(!g[x].size()&& !f[x]){f[x]=tim; tim++;}
  rep(i,g[x].size()){
    if(!d[g[x][i]])dfs(g[x][i]);
    if(i==g[x].size()-1&& !f[x]){f[x]=tim;tim++;}
  }
}
int restart=0;
bool owari(vector<int>l){
  rep(i,n){
    if(l[i+1]==0){return false;}
  }
  return true;
}
signed main() {

   cin>>n;
   rep(i,n){
     int t,m;cin>>t>>m;
     rep(j,m){int k; cin>>k; if(k!=i+1){g[i+1].push_back(k);}}
   }

   while(!owari(d)){
     int restart=0;
     rep(i,n){if(d[i+1]==0){restart=i+1;break;}}
     dfs(restart);
   }
   rep(i,n){
     cout<<i+1<<' '<<d[i+1]<<' '<<f[i+1]<<endl;
   }
}

C++: #include <cstdio>
#include <stack>
using namespace std;

#define start first
#define end second

static const int NOT   = false;
static const int WHITE = 1;
static const int GRAY  = 2;
static const int BLACK = 3;
static const int N	   = 101;

int  n;
int  VisitedInfo[N];
bool Graph[N][N];
pair< int, int > Time[N];

void dfs( int u );
int  nextNode( int u );

int main()
{

	int u, k, v;

	for( int i = 0; i < N; i++ ) {
		for( int j = 0; j < N; j++ ) Graph[i][j] = NOT;
		VisitedInfo[i] = WHITE;
	}

	scanf( "%d", &n );
	for( int i = 0; i < n; i++ ) {
		
		scanf( "%d %d", &u, &k );
		for( int j = 0; j < k; j++ ) {

			scanf( "%d", &v );
			Graph[u][v] = true;

		}

	}

	dfs( 1 );

	for( int i = 1; i <= n; i++ ) printf( "%d %d %d\n", i, Time[i].start, Time[i].end );

	return 0;

}

void dfs( int u )
{

	int time = 1;
	stack< int > dfsInfo;

	dfsInfo.push( u );
	Time[u].start  = time;
	VisitedInfo[u] = GRAY;

	while( !dfsInfo.empty() ) {

		int ppos = dfsInfo.top();
		int pos  = nextNode( ppos );

		if( pos != 0 ) {
			if( VisitedInfo[pos] == WHITE ) {

				dfsInfo.push( pos );
				Time[pos].start  = ++time;
				VisitedInfo[pos] = GRAY;

			}
		}
		if( pos == 0 && VisitedInfo[ppos] != WHITE ){

			dfsInfo.pop();
			Time[ppos].end	  = ++time;
			VisitedInfo[ppos] = BLACK;

		}

	}

}

int nextNode( int now )
{

	for( int i = 1; i <= n; i++ ) {
		if( Graph[now][i] && VisitedInfo[i] == WHITE ) return i;
	}

	return 0;

}