Go: package main

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

type TimeRecord struct {
	discoverTime int
	finishTime   int
}

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	n, err := nextInt(sc)
	if err != nil {
		panic(err)
	}

	timeRecordMap := make([]TimeRecord, n)
	childrenMap := make([][]int, n)
	for i := 1; i <= n; i++ {
		node, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		timeRecordMap[node-1] = TimeRecord{-1, -1}

		childNum, err := nextInt(sc)
		if err != nil {
			panic(err)
		}
		childrenMap[node-1] = make([]int, childNum)
		for j := 0; j < childNum; j++ {
			child, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			childrenMap[node-1][j] = child
		}
	}

	timer := 1
	for {
		startNode := findStartNode(childrenMap, timeRecordMap)
		if startNode > 0 {
			visit(startNode, &timer, childrenMap, timeRecordMap)
		} else {
			break
		}
	}
	for k, v := range timeRecordMap {
		fmt.Printf("%d %d %d\n", k+1, v.discoverTime, v.finishTime)
	}
}

func findStartNode(childrenMap [][]int, timeRecordMap []TimeRecord) int {
	x := -1
	for node, timeRecord := range timeRecordMap {
		if timeRecord.discoverTime < 0 {
			x = node + 1
			break
		}
	}
	if x < 0 {
		return -1
	}

	found := false
	i := 0
	for i < len(childrenMap) {
		children := childrenMap[i]
		for j := 0; j < len(children); j++ {
			if children[j] == x {
				x = j + 1
				found = true
				break
			}
		}
		if found {
			i = 0
		} else {
			i++
		}
	}
	return x
}

func visit(currentNode int, timer *int, childrenMap [][]int, timeRecordMap []TimeRecord) {
	if timeRecordMap[currentNode-1].discoverTime > 0 {
		return
	}
	children := childrenMap[currentNode-1]
	timeRecordMap[currentNode-1] = TimeRecord{*timer, timeRecordMap[currentNode-1].finishTime}
	(*timer)++
	for i := 0; i < len(children); i++ {
		visit(children[i], timer, childrenMap, timeRecordMap)
	}
	timeRecordMap[currentNode-1] = TimeRecord{timeRecordMap[currentNode-1].discoverTime, *timer}
	(*timer)++
}

func nextInt(sc *bufio.Scanner) (int, error) {
	sc.Scan()
	return strconv.Atoi(sc.Text())
}

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

const int MAX_N = 100;
const int WHITE = -1;
const int GRAY = -2;
const int BLACK = -3;

int n;
int color[MAX_N];
bool adj[MAX_N][MAX_N];
int d[MAX_N], f[MAX_N];

int t;

void dfs(int u) {
    color[u] = GRAY;
    d[u] = ++t;
    for (int v = 0; v < n; v++) {
        if (adj[u][v] && color[v] == WHITE) {
            dfs(v);
        }
    }
    color[u] = BLACK;
    f[u] = ++t;
}

void dfs_init(void) {
    t = 0;
    for (int i = 0; i < n; i++) {
        color[i] = WHITE;
    }
    for (int i = 0; i < n; i++) {
        if (color[i] == WHITE) {
            dfs(i);
        }
    }
}

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

    dfs_init();

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

    return 0;
}

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

vector<int>tree[120];
int c[120], d[120],f[120];
int N,t=0;

void dfs_visit(int u){
  c[u]=1;
  t++;
  d[u]=t;
  for (auto p : tree[u]) {
    if(c[p]==0) dfs_visit(p);
  }
  c[u]=2;
  t++;
  f[u]=t;

}


void dfs(){

  for(int u=0;u<N;u++) c[u]=0;
  for(int u=0;u<N;u++){
    if(c[u]==0) dfs_visit(u);
  }

}

int main() {

  cin >>N;

  //vector<vector<int>> data(N, vector<int>(N));

  for(int j=0;j<N;j++){
  int u,k;
  cin>>u>>k;
    for(int i=0;i<k;i++){
      int v;
      cin>>v;
      tree[u-1].push_back(v-1);
    }
  }

	dfs();

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

C++: #define _CRT_SECURE_NO_WARNINGS
#include<cstdio>

bool table[102][102] = {};
int color[102] = {}; //0:?????¢?´¢???1:?¨??????????, 2:??¢?´¢??????
int n, counter = 0;
int t_visit[102] = {};
int t_finish[102] = {};

void DFS(int y) {
	
	for (int j = 0; j <= n - 1;j++) {

		//?¨????or??¢?´¢???????????£???????????????
		if ((table[y][j] == 1)&&(color[j] == 0)) {
			color[y] = 1; //?¨???????????????????
			if (t_visit[y] == 0) t_visit[y] = ++counter;
			DFS(j);
		}

	}

	color[y] = 2; //??¢?´¢???????????????
	if (t_visit[y] == 0) t_visit[y] = ++counter;
	if (t_finish[y] == 0) t_finish[y] = ++counter;
	
}

int main(void) {
	int u, k, s;

	scanf("%d", &n);

	for (int i = 0;i <= n - 1;i++) {
		scanf("%d %d", &u, &k);
		for (int j = 0;j <= k - 1;j++) {
			scanf("%d", &s);
			table[u - 1][s - 1] = 1;
		}
	}


	for (int i = 0;i <= n - 1;i++) {
		if (color[i] == 0) {
			DFS(0);
		}
	}


	for (int i = 0; i <= n - 1;i++) {
		printf("%d %d %d\n", i + 1, t_visit[i], t_finish[i]);
	}

	return 0;
}

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

vector<int> graph[100];
int d[100], f[100];
int visited = 0;

void dfs(int id){
    d[id] = visited + 1;
    for(int i = 0; i < graph[id].size(); i++)
	{
        if(graph[id][i] != id && !d[graph[id][i]] && !f[graph[id][i]])
		{
			dfs(graph[id][i]);
		}
    }
    f[id] = visited + 1;
}

int main(){
    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;
            graph[u - 1].push_back(v - 1);
        }
    }
    dfs(0);
    for(int i = 0;i < n;i++)
	{
        if(!f[i]) 
		{
			dfs(i);
		}
    }
    for(int i = 0;i < n;i++)
	{
        cout << i + 1 << " " << d[i] << " " << f[i] << endl;
    }
    return 0;
}

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

int n;
vector<vector<int> > A;
vector<vector<int> > T;
int t = 0;

void dfs(int cur){ // cur????¨????
    // cur ????¨??????????????¨????
    t += 1;
    T[cur][0] = t;
    // ???????¢??????¨??¨???
    // cerr << "visiting " << cur << " " << t << endl;

    for(int dst = 0; dst < n; ++dst){ // ??¨???????????? dst ????????????
        if(A[cur][dst] == 1 && T[dst][0] == -1){ // cur??????dst??????????????????,dst???????¨??????????
            dfs(dst);
        }
    }
    // cur ????¨????????????????????¨????
    t += 1;
    T[cur][1] = t;
    // ??¢??°?????????????????????????????? (?????¢??°)
    return; // ?????\???
}

int main(){
    cin >> n;
    A = vector<vector<int> >(n, vector<int>(n, 0));
    T = vector<vector<int> >(n, vector<int>(2, -1));
    for(int i=0; i<n; ++i){
        int k;
        cin >> k;
        // 1~n???index?????¨????????????????????????????????????1????????????0~n-1????????????
        k -= 1;
        int u;
        cin >> u;
        for(int j=0; j<u; ++j){
            int v;
            cin >> v;
            v -= 1;
            A[k][v] = 1;
        }
    }
    for(int i=0; i<n; ++i){
        if(T[i][0] == -1){
          dfs(i);
        }
    }
    for(int i=0; i<n; ++i){
        cout << i+1 << " " << T[i][0] << " " << T[i][1] << endl;
    }
}

C++: #include <cstdio>

typedef struct{
	bool isVisited;
	int degree;
	int start;
	int end;
	int *neighbors;
} node;

int count = 1;

void dfs(node* nodes, int id){
	nodes[id].isVisited = true;
	if (nodes[id].start == 0) nodes[id].start=count;
	for (int i=0; i<nodes[id].degree; i++){
		if (!nodes[nodes[id].neighbors[i]].isVisited){
			count ++;
			dfs(nodes, nodes[id].neighbors[i]);
		}
	}
	count++;
	nodes[id].end = count;
}

int main(){
	int n, d, r, id;
	node *nodes;

	scanf("%d", &n);
	nodes = new node[n];
	for (int i=0; i<n;i++){
		nodes[i].isVisited=false;
		scanf("%d %d", &r, &d);
		nodes[i].degree=d;
		nodes[i].neighbors = new int[d];
		nodes[i].start = 0;
		
		for (int j=0;j<d;j++){
			scanf("%d", &id);
			nodes[i].neighbors[j] = id-1;
		}
	}

	dfs(nodes, 0);
	for (int i=0; i<n;i++){
		printf("%d %d %d\n", i, nodes[i].start, nodes[i].end);
		delete []nodes[i].neighbors;
	}
	delete []nodes;
	return 0;
}