Go: package main

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

const (
	initialBufSize = 100000
	maxBufSize     = 1000000
)

var sc *bufio.Scanner

func initScanner(r io.Reader) *bufio.Scanner {
	buf := make([]byte, initialBufSize)

	sc := bufio.NewScanner(r)
	sc.Buffer(buf, maxBufSize)
	sc.Split(bufio.ScanWords) // bufio.ScanLines
	return sc
}

func main() {
	sc = initScanner(os.Stdin)
	resolve(parseProblem())
}

type graph struct {
	size  int
	edges [][]int
}

func parseProblem() *graph {
	n := scanInt(sc)
	g := &graph{
		size:  n,
		edges: make([][]int, n),
	}
	for i := 0; i < g.size; i++ {
		_ = scanInt(sc)
		k := scanInt(sc)
		g.edges[i] = make([]int, k)
		for j := 0; j < k; j++ {
			g.edges[i][j] = scanInt(sc) - 1
		}
	}
	return g
}

func resolve(g *graph) {
	ds := make([]int, g.size)
	fs := make([]int, g.size)
	time := 0
	for i := 0; i < len(ds); i++ {
		if ds[i] == 0 {
			time++
			time = _dfs(ds, fs, time, g, i)
		}
	}
	for i := 0; i < len(ds); i++ {
		fmt.Println(i+1, ds[i], fs[i])
	}
	return
}

func _dfs(ds, fs []int, time int, g *graph, idx int) int {
	ds[idx] = time
	for _, next := range g.edges[idx] {
		if ds[next] > 0 {
			continue
		}
		time++
		time = _dfs(ds, fs, time, g, next)
	}
	time++
	fs[idx] = time
	return time
}

// snip-scan-funcs
func scanInt(sc *bufio.Scanner) int {
	sc.Scan()
	i, _ := strconv.Atoi(sc.Text())
	return int(i)
}
func scanString(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

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

int t = 0;

void dfs(vector<vector<int>> &adj_list, vector<vector<int>> &res, int u)
{
    res[u][0] = ++t;
    for (int i = 0; i < adj_list[u].size(); i++)
    {
        int v = adj_list[u][i];
        if (res[v][0] == 0)
        {
            dfs(adj_list, res, v);
        }
    }
    res[u][1] = ++t;
}

int main()
{
    int n;
    cin >> n;

    vector<vector<int>> adj_list(n);
    for (int i = 0; i < n; i++)
    {
        int id, k;
        cin >> id >> k;
        for (int j = 0; j < k; j++)
        {
            int u;
            cin >> u;
            adj_list[id - 1].push_back(u - 1);
        }
    }

    vector<vector<int>> res(n, vector<int>(2, 0));
    for (int i = 0; i < n; i++)
    {
        if (res[i][0] == 0)
        {
            dfs(adj_list, res, i);
        }
    }

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

    return 0;
}

C++: #include<cstdio>
#include<stack>
using namespace std;
const char N_MAX = 105;
char n;
unsigned char time=0;
stack<int> sta;
bool matrix[N_MAX][N_MAX];
struct Node{
    //0:undiscovered 1:active 2:end
    char state;
    unsigned char stTime, endTime;
};
Node V[N_MAX];
void buildMatrix(){
	for(char i=0; i<n;i++){
		int degree, index;
		scanf("%u%u", &index, &degree);
		for(char j=0; j<degree; j++){
			int temp;
			scanf("%d", &temp);
			matrix[index-1][temp-1] = true;
		}
	}
}
char next(char num){
    for(char i=0;i<n;i++){
        if(matrix[num][i]&&V[i].state==0){
            return i;
        }
    }
    return -1;
}
void dfs() {
    for(char i = 0; i < n; i++) {
        if(V[i].state == 0) {
            sta.push(i);
            V[i].stTime = ++time;
            V[i].state = 1;
            while(!sta.empty()) {
                char active = sta.top();
                char nex = next(active);
                if(nex != -1) {
                    sta.push(nex);
                    V[nex].stTime = ++time;
                    V[nex].state = 1;
                } else {
                    sta.pop();
                    V[active].endTime = ++time;
                    V[active].state = 2;
                }
            }
        }
    }
}
int main(){
    scanf("%d", &n);
    buildMatrix();
    dfs();
    for(char i=0;i<n;i++){
        printf("%d %d %d\n", i+1, V[i].stTime, V[i].endTime);
    }
}

C++: #include <stdio.h>
#include <stdint.h>
#include <iostream>
#include <fstream>
#include <cassert>
#include <climits>

#include <vector>
#include <memory>
using namespace std;

#define DEBUG (0)
#define USE_UNIQUE_PTR (0)

#if DEBUG
#define DPRINTF(...) do { \
    printf("D(L%d) %s: ", __LINE__, __func__); \
    printf(__VA_ARGS__); \
  } while (false)
#else
#define DPRINTF(...)
#endif // DEBUG

int g_num = -1;
int g_time = 1;

class Vertex {
public:
  Vertex() :
    id_(-1),
    discover_time_(-1),
    finish_time_(-1),
    adjacentNum_(0),
    adjacentIds_(nullptr),
    isVisited_(false) { }

  ~Vertex() {
#if !USE_UNIQUE_PTR
    if (adjacentIds_)
      delete [] adjacentIds_;
#endif
  }

  void setAdjacency(const vector<int> &adjacentIds);

  inline void setId(int id) { id_ = id; }
  inline void setDiscoverTime(int time) { discover_time_ = time; }
  inline void setFinishTime(int time) { finish_time_ = time; }
  inline void setVisited(bool visited) { isVisited_ = visited; }

  inline int getId() { return id_; }
  inline int getDiscoverTime() { return discover_time_; }
  inline int getFinishTime() { return finish_time_; }
  inline bool getVisited() { return isVisited_; }
  inline int getAdjacentNum() { return adjacentNum_; }
  inline int getAdjacentId(int idx) {
    if (adjacentIds_ == nullptr || idx > adjacentNum_)
      return -1;
    return adjacentIds_[idx];
  }

  void printTime();
  void printAdj();

private:
  int id_;
  int discover_time_;
  int finish_time_;

  int adjacentNum_;
#if USE_UNIQUE_PTR
  unique_ptr<int[]> adjacentIds_;
#else
  int *adjacentIds_;
#endif // USE_UNIQUE_PTR

  bool isVisited_;
};


void Vertex::setAdjacency(const vector<int> &adjacentIds)
{
  if (adjacentIds_) assert(1);

  adjacentNum_ = adjacentIds.size();
#if USE_UNIQUE_PTR
  adjacentIds_ = unique_ptr<int[]>(new int[adjacentNum_]);
#else
  adjacentIds_ = new int[adjacentNum_];
#endif // USE_UNIQUE_PTR

  for (int i = 0; i < adjacentNum_; i++)
  {
    adjacentIds_[i] = adjacentIds[i];
  }

}

void Vertex::printTime()
{
  printf("%d %d %d\n", id_, discover_time_, finish_time_);
}

void Vertex::printAdj()
{
  DPRINTF("%d %d", id_, adjacentNum_);
  for (int i = 0; i < adjacentNum_; i++) {
    printf(" %d", adjacentIds_[i]);
  }
  cout << endl;
}


void dfs(Vertex vertices[], int idx)
{

  DPRINTF("time %d  idx %d\n", g_time, idx);

  assert(idx <= g_num);

  Vertex &vtx = vertices[0];

  if (!vtx.getVisited())
  {
    vtx.setDiscoverTime(g_time);
    g_time++;
  }

  for (int i = 0; i < vtx.getAdjacentNum(); i++)
  {
    int id = vtx.getAdjacentId(i);
    dfs(vertices, id);
  }

  if (!vtx.getVisited())
  {
    vtx.setFinishTime(g_time);
    vtx.setVisited(true);
    g_time++;
  }

}


int main()
{
  //int n;

  //cin >> n; cin.ignore();
  cin >> g_num; cin.ignore();
  DPRINTF("Node num %d\n", g_num);

  Vertex vertices[g_num+1];

  for (int i = 1; i <= g_num; i++)
  {
    int id;
    int num;

    cin >> id >> num;
    vertices[i].setId(id);
    DPRINTF("node %d (num %d)\n", id, num);

    vector<int> adjs;

    for (int j = 0; j < num; j++)
    {
      int adj;
      cin >> adj;

      adjs.push_back(adj);
    }

    if (adjs.size())
      vertices[i].setAdjacency(adjs);

    cin.ignore();
  }

#if DEBUG
  for (int i = 1; i <= g_num; i++) vertices[i].printAdj();
#endif

  for (int i = 1; i <= g_num; i++)
    if (!vertices[i].getVisited())
      dfs(vertices, i);

  for (int i = 1; i <= g_num; i++) vertices[i].printTime();

  return 0;
}

C++: #include <queue>
#include <map>
#include <cstdio>
#include <algorithm>
using namespace std;
map<int,vector<int> >a;
map<int,int>m;
vector<pair<int,pair<int,int> > >v;
int T;
void D(int k){
	m[k]=1;
	int t=T;
	for(int i=0;i<a[k].size();i++)if(!m[a[k][i]])++T,D(a[k][i]);
	T++;
	v.push_back(make_pair(k,make_pair(t,T)));
}
main(){
	int i,j,k,n;
	for(scanf("%d",&n);n--;)for(scanf("%d%d",&i,&k);k--;a[i].push_back(j))scanf("%d",&j);
	D(T=1);
	sort(v.begin(),v.end());
	for(i=0;i<v.size();i++)printf("%d %d %d\n",v[i].first,v[i].second.first,v[i].second.second);
}