Go: package main

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

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)
	sc.Scan()
	num, _ := strconv.Atoi(sc.Text())
	nodes := make(map[int]*node)

	for i := 0; i < num; i++ {
		sc.Scan()
		id, _ := strconv.Atoi(sc.Text())
		sc.Scan()
		nodeNum, _ := strconv.Atoi(sc.Text())
		n := node{id, make([]int, 0), 0, 0}
		for j := 0; j < nodeNum; j++ {
			sc.Scan()
			nid, _ := strconv.Atoi(sc.Text())
			n.nexts = append(n.nexts, nid)
		}
		nodes[id] = &n
	}

	s := Stack{}
	for i := 1; i < len(nodes)+1; i++ {
		if nodes[i].s != 0 {
			continue
		}
		walk(i, &nodes, s)
	}
	for i := 1; i < len(nodes)+1; i++ {
		fmt.Printf("%v %v %v\n", (*nodes[i]).id, (*nodes[i]).s, (*nodes[i]).e)
	}
}

var time int

func walk(nid int, nodes *map[int]*node, s Stack) {
	n := (*nodes)[nid]
	if n.s != 0 {
		return
	}
	time++
	n.s = time
	s.Push(n)
	for _, v := range n.nexts {
		walk(v, nodes, s)
	}
	time++
	n.e = time
}

type node struct {
	id    int
	nexts []int
	s     int
	e     int
}

// Stack is Stack
type Stack struct {
	stack []interface{}
}

// Push new value
func (stack *Stack) Push(val interface{}) {
	stack.stack = append(stack.stack, val)
}

// Pop new value
func (stack *Stack) Pop() interface{} {
	val := stack.stack[len(stack.stack)-1]
	stack.stack = stack.stack[0 : len(stack.stack)-1]
	return val
}

C++: #include <iostream>
using namespace std;
int d[101] = {},f[101];
int a[101][101];
int kosu[101];
int joutai = 0;
void dfs(int x){
	joutai++;
	d[x] = joutai;
	for(int i = 1;i <= kosu[x];i++){
		if(d[a[x][i]] == 0){
			dfs(a[x][i]);
		}
	}
	joutai++;
	f[x] = joutai;
}

int main(){
	int n,x;
	cin >> n;
	for(int i = 0;i < n;i++){
		cin >> x;
		cin >> kosu[x];
		for(int j = 1;j <= kosu[x];j++){
			cin >> a[x][j];
		}
	}
	for(int i = 1;i <= n;i++){
		if(d[i] == 0){
			dfs(i);	
		}	
	}

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

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

void read_data(int n, vector<vector<int>> & Es){
    int u = 0, k = 0, v = 0;
    while (n--){
        cin >> u;
        cin >> k;
        while (k--){
            cin >> v;
            Es[u - 1].push_back(v - 1);
        }
    }
}

void display_result(int n, vector<int> & d, vector<int> & f){
    for (int i = 0; i != n; ++i){
        cout << i + 1 << ' ' << d[i] << ' ' << f[i] << endl;
    }
}

void dfs(int node, int & time, vector<vector<int>> & Es, vector<int> & d, vector<int> & f ){
    if (d[node]) return;
    d[node] = time;
    ++time;
    for (auto next_node : Es[node]){
        dfs(next_node, time, Es, d, f);
    }
    f[node] = time;
    ++time;
}

int main()
{
    int n = 0;
    cin >> n;
    vector< vector<int> > Es(n);
    vector<int> d(n, 0);
    vector<int> f(n, 0);
    read_data(n, Es);
    int node = 0;
    int time = 1;
    dfs(node, time, Es, d, f);
    display_result(n, d, f);
    
    return 0;
}

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

using namespace std;

int G[100][100];
int In[100];
int Out[100];
void init() {
	for (int i = 0; i < 100; i++) {
		for(int j = 0; j < 100; j++)
			G[i][j] = 0;
		In[i] = -1;
		Out[i] = -1;
	}	
}

void dfs(int src);

int main() {
	init();
	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_j;
			cin >> v_j;
			G[u - 1][v_j - 1] = 1;
		}
	}
	dfs(0);
	for (int i = 0; i < n; i++)
		cout << i + 1 << " " << In[i] << " " << Out[i] << endl;
}

int time = 1;

void dfs(int cur) {
	In[cur] = time;
	time++;
	for (int dst = 0; dst < 100; dst++)
		if (G[cur][dst] == 1 && In[dst] == -1)
			dfs(dst);
	Out[cur] = time;
	time++;
}

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

using namespace std;

int n, u, k, v, d[110], f[110], time=0;
bool vis[110];
vector<int> adj[110];

void dfs (int p)
{
    time++;
    vis[p]=true;
    d[p]=time;
    for (auto u : adj[p])
    {
        if (!vis[u]) dfs(u);
    }
    time++;
    f[p]=time;
}

int main()
{
    memset(vis, false, sizeof(vis));
    cin>>n;
    for (int i=0; i<n; i++)
    {
        cin>>u>>k;
        for (int j=0; j<k; j++)
        {
            cin>>v;
            adj[u].push_back(v);
        }
    }
    dfs(1);
    for (int i=1; i<=n; i++)
    {
        cout<<i<<' '<<d[i]<<' '<<f[i]<<'\n';
    }
    return 0;
}

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

typedef long long ll;
#define inf 1e9+7

int f[200],d[200];
bool table[200][200];
int cou;

void init(){
    for(int i=0;i<200;i++){
        f[i]=d[i]=-1;
    }
}

void dfs(int n,int itr){
    cou++;
    if(d[itr]<0)d[itr]=cou;
    for(int i=0;i<n;i++){
        if(d[i]<0&&table[itr][i]) dfs(n,i);
    }
    cou++;
    f[itr] = cou;
}

void solve(int n){
    for(int i=0;i<n;i++){
        if(d[i]<0)dfs(n,i);
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);


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

    solve(n);

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

    return 0;
}

C++: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <climits>
#include <stack>

using namespace std;

int main() {
	stack<int> S;

	int n;
	int u, v;
	int AdjList[101][99];
	int next[101];
	int Deg[101];
	bool Visited[101];
	int d[101], f[101], time;
	int i, j;
	cin >> n;
	for (i = 1; i <= n; i++) {
		Visited[i] = false;
		next[i] = 0;
		d[i] = 0;
		cin >> u;
		cin >> Deg[u];
		for (j = 0; j < Deg[u]; j++) {
			cin >> v;
			AdjList[u][j] = v;
		}
	}

	time = 1;
	for (i = 1; i <= n; i++) {
		if (Visited[i] != true) {
			v = i;
			S.push(v);
			while (S.empty() != true) {
				v = S.top();
				if (d[v] == 0) {
					d[v] = time++;
				}
				Visited[v] = true;
				for (i = next[v]; i < Deg[v]; i++) {
					u = AdjList[v][i];
					if (Visited[u] != true) {
						S.push(u);
						break;
					}
				}
				if (i == Deg[v]) {
					S.pop();
					f[v] = time++;
				}
				else {
					next[v] = i + 1;
				}
			}
		}
	}

	for (i = 1; i <= n; i++) {
		printf("%d %d %d\n", i, d[i], f[i]);
	}

	return 0;

}

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

#define MAX 105
#define WHITE 0
#define GRAY 1
#define BLACK 2

int n, M[MAX][MAX];
int color[MAX], d[MAX], f[MAX], timer;
int nt[MAX];

//uに隣接するvを小さい方から取得
int next(int u){
    for(int v=nt[u]; v<=n; v++){
        nt[u] = v+1;
        if(M[u][v]) return v;
    }
    return -1;
}

void dfs_visit(int r){
    for(int u=1; u<=n; u++) nt[u] = 1;

    stack<int> S;
    S.push(r);
    color[r] = GRAY;
    timer++;
    d[r] = timer;

    while(!(S.empty())){
        int u = S.top();
        int v = next(u);
        if(v != -1){
            //隣接してて行けるところがある
            if(color[v] == WHITE){
                color[v] = GRAY;
                timer++;
                d[v] = timer;
                S.push(v);
            }
        }else{
            //もう隣接してて行けるところがない
            S.pop();
            color[u] == BLACK;
            timer++;
            f[u] = timer;
        }
    }
}

void dfs(){
    //初期化
    for(int u=1; u<=n; u++){
        color[u] = WHITE;
        nt[u] = 1;
    }
    timer = 0;

    //各頂点に対して白なら訪問する。
    for(int u=1; u<=n; u++){
        if(color[u] == WHITE) dfs_visit(u);
    }
    //出力
    for(int u=1; u<=n; u++){
        printf("%d %d %d\n", u, d[u], f[u]);
    }
}

//グラフの深さ優先探索(再帰を用いる)
int main(){
    cin >> n;
    //隣接リスト表現→隣接行列表現への変換
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            M[i][j] = 0;
        }
    }
    for(int i=1; i<=n; i++){
        int u, k;
        cin >> u >> k;
        for(int j=1; j<=k; j++){
            int v;
            cin >> v;
            M[u][v] = 1;
        }
    }

    dfs();

    return 0;
}