Go: package main

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

func main() {
	scn := bufio.NewScanner(os.Stdin)
	scn.Split(bufio.ScanWords)
	nextInt := func() int { scn.Scan(); r, _ := strconv.Atoi(scn.Text()); return r }
	w := bufio.NewWriter(os.Stdout)

	n := nextInt()
	vecs := make([][]int, n)
	for i := 0; i < n; i++ {
		u := nextInt()
		k := nextInt()
		for j := 0; j < k; j++ {
			vecs[u-1] = append(vecs[u-1], nextInt()-1)
		}
	}

	ds := make([]int, n)
	fs := make([]int, n)
	founds := make([]bool, n)
	t := 0
	for i := range founds {
		if !founds[i] {
			t = dfs(vecs, ds, fs, founds, i, t)
		}
	}

	for i := 0; i < n; i++ {
		fmt.Fprintln(w, i+1, ds[i], fs[i])
	}

	w.Flush()
}

func dfs(vecs [][]int, ds, fs []int, founds []bool, i, t int) (time int) {
	t++
	ds[i] = t
	founds[i] = true
	for _, v := range vecs[i] {
		if !founds[v] {
			t = dfs(vecs, ds, fs, founds, v, t)
		}
	}
	t++
	fs[i] = t

	return t
}

C++: #include <iostream>
#include <vector>

using namespace std;

int N,k[1000];
int v[1000][1000];
int found[1000] = {0},ended[1000] = {0};
int keep;
int checking=0;

void dfs(int cur);

int main() {
	cin >> N;
	for(int i=1;i<N+1;i++) {
		cin >> keep >> k[i];
		for(int j=1;j<k[i]+1;j++) {
			cin >> v[i][j];

		}
	}
	dfs(1);
	while(true) {
		//cout << "processing..." << endl;
		bool flag = false;
		int key = 1;
		for(int i=1;i<N+1;i++) {
			if(found[i] == 0) {
				flag = true;
				key = i;
				break;
			}
		}
		if(flag) {
			dfs(key);
		} else {
			break;
		}
	}
	
	
	for(int i=1;i<N+1;i++) {
		cout << i << " " << found[i] << " " << ended[i] << endl;
	}
	

}

void dfs(int cur) {
	bool REkirrer = false;
	for(int i=1;i<N+1;i++) {
		if(found[i] == 0) {
			REkirrer = true;
		}
	}
	if(!REkirrer) return;
	int loopcount=0;
	//cout << "process ended" << endl;
	if(!found[cur]) {
		checking++;
		//cerr << "visiting: " << cur << " " << "time: " << checking << endl;
		found[cur] = checking;

	}
	for(int dst=1;dst<N+1;dst++) {
		loopcount++;
		bool flag = false;
		for(int i=1;i<k[cur]+1;i++) {
			if(v[cur][i] == dst) flag = true;
		}
		if((flag) && (dst != cur)) dfs(dst);
	}
	if(!ended[cur]) {
		checking++;
		//cerr << "ended: " << cur << " " << "time: " << checking << endl;
		ended[cur] = checking;
	}
}

C++: #include <iostream>
#include <cstdio>
#include <vector>
#include <stack>
#include <string>
#include <queue>

using namespace std;

int d[101];
int f[101];
bool isUsed[101];
int time = 0;

void DFS(vector< vector<int> >& G, int vertex)
{
	d[vertex] = ++time;
	for (int i = 0; i < G[vertex].size(); ++i)
	{
		if (G[vertex][i] == 1 && isUsed[i] == false)
		{
			isUsed[i] = true;
			DFS(G, i);
		}
	}
	f[vertex] = ++time;
}

void solve()
{
	int n;
	cin >> n;
	vector< vector<int> > G(n, vector<int>(n));
	for (int i = 0; i < n; ++i)
	{
		int u, k;
		cin >> u >> k;
		--u;
		for (int j = 0; j < k; ++j)
		{
			int v;
			cin >> v;
			--v;
			G[u][v] = 1;
		}
	}
	for (int i = 0; i < 101; ++i)
	{
		isUsed[i] = false;
	}
	isUsed[0] = true;
	DFS(G, 0);
	for (int i = 0; i < n; ++i)
	{
		cout << i + 1 << " " << d[i] << " " << f[i] << endl;
	}
}

int main()
{
	solve();
	return(0);
}

C++: #include <iostream>
#include <stack>

using namespace std;

#define MAX 110
int num;
int matrix[MAX][MAX];
int dst[MAX];
int counter = 0;
int D[MAX];
int F[MAX];

void input(){
    cin >> num;
    for(int i=0;i<MAX;i++){
        dst[i] = -1;
        for(int j=0;j<MAX;j++){
            matrix[i][j] = 0;
        }
    }
    for(int i=1;i<=num;i++){
        int v; cin >> v;
        int tmp; cin >>tmp;
        for(int j=0;j<tmp;j++){
            int vi; cin >> vi;
            matrix[v-1][vi-1] = 1;
        }
    }
}

void dfs(int cur){
    counter++;
    D[cur] = counter;
    for(int i=0; i< num;i++){
        if(matrix[cur][i] == 1 && D[i]== 0)
            dfs(i);
    }
    F[cur] = counter+1;
    counter++;
    return;
}

int main(){
    input();
    for(int i=0;i<MAX;i++){
        D[i] = 0;
        F[i] = 0;
    }
    dfs(0);
    for(int i=0;i<num;i++){
        cout << i+1 << " " << D[i] << " " << F[i] << endl;
    }
}

C++: #include <iostream>
#include <algorithm>
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; i++)
            if(r[n][i]) dfs(i);
        f[n] = p++;
    }
}

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

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

struct StSeq
{
  int m_nBgn;
  int m_nEnd;

  StSeq() : m_nBgn(0), m_nEnd(0)
  { }
};

void fnInput(vector<vector<int>>& rvvnAdjcy, vector<StSeq>& rvoDFSrch)
{
  int nMaxSiz;
  cin >> nMaxSiz;

  rvvnAdjcy.resize(nMaxSiz + 1, vector<int>(nMaxSiz + 1, 0));
  for (int i = 0; i < nMaxSiz; ++i)
  {
    int nx, nSecSiz;
    cin >> nx >> nSecSiz;
    for (int j = 0; j < nSecSiz; ++j)
    {
      int ny;
      cin >> ny;
      rvvnAdjcy[nx][ny] = 1;
    }
  }
  StSeq oSeq;
  rvoDFSrch.resize(nMaxSiz + 1, oSeq);
}

void fnDepthFirstSearch(const vector<vector<int>>& cnrvvnAdjcy, vector<StSeq>& rvoDFSrch, int nx)
{
  static int stnCnt = 0;

  if (rvoDFSrch[nx].m_nBgn)  return;
  rvoDFSrch[nx].m_nBgn = ++stnCnt;

  for (int ny = 1; ny < cnrvvnAdjcy.size(); ++ny)
    if (cnrvvnAdjcy[nx][ny] == 1  &&
        nx != ny               )
      fnDepthFirstSearch(cnrvvnAdjcy, rvoDFSrch, ny);

  rvoDFSrch[nx].m_nEnd = ++stnCnt;
}

void fnResult(const vector<StSeq>& cnrvoDFSrch)
{
  for (int i = 1; i < cnrvoDFSrch.size(); ++i)
    cout << i <<  " " << cnrvoDFSrch[i].m_nBgn << " " << cnrvoDFSrch[i].m_nEnd << endl;
}

int main()
{
  cin.tie(0);
  ios::sync_with_stdio(false);
  vector<vector<int>> vvnAdjcy;
  vector<StSeq> voDFSrch;

  fnInput(vvnAdjcy, voDFSrch);
  for (int nx = 1; nx < voDFSrch.size(); ++nx)
    fnDepthFirstSearch(vvnAdjcy, voDFSrch, nx);
  fnResult(voDFSrch);

  return 0;
}