Go: package main

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

//util
var sc = bufio.NewScanner(os.Stdin)

func nextStr() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	sc.Scan()
	i, e := strconv.Atoi(sc.Text())
	if e != nil {
		panic(e)
	}
	return i
}

func printList(list []int) {
	n := len(list)
	buf := bufio.NewWriter(os.Stdout)
	for _, v := range list[0 : n-1] {
		buf.Write([]byte(fmt.Sprintf("%d ", v)))
	}
	buf.Write([]byte(fmt.Sprintf("%d\n", list[n-1])))
	buf.Flush()
}

func max(a, b int) int {
	if a > b {
		return a
	} else {
		return b
	}
}

func min(a, b int) int {
	if a > b {
		return b
	} else {
		return a
	}
}

//solve

const MAX = 100
const WHITE = 0
const GRAY = 1
const BLACK = 2

var time, n int

//隣接行列
var M [MAX][MAX]int

//d[i]: 最初にiを訪問した時刻。発見時刻
//f[i]: iの隣接リストを訪問し終えた時刻。完了時刻
var color, d, f [MAX]int

func dfs_visit(u int) {
	color[u] = GRAY
	time++
	d[u] = time
	//隣接を調べる
	for v := 0; v < n; v++ {
		if M[u][v] == 0 {
			continue
		}
		//隣接するvが、未訪問だった場合
		if color[v] == WHITE {
			dfs_visit(v)
		}
	}
	//訪問完了処理
	color[u] = BLACK
	time++
	f[u] = time
	//訪問完了
}

func dfs() {
	//初期化
	for u := 0; u < n; u++ {
		color[u] = WHITE
	}
	time = 0

	//未訪問のuを始点として、深さ優先探索
	for u := 0; u < n; u++ {

		if color[u] == WHITE {
			dfs_visit(u)
		}
	}

	for u := 0; u < n; u++ {
		fmt.Println(u+1, d[u], f[u])
	}
}

func main() {
	sc.Split(bufio.ScanWords)
	n = nextInt()
	for i := 0; i < n; i++ {
		u, k := nextInt(), nextInt()
		M[u-1][u-1] = 0

		//fmt.Println(u, k)
		if k > 0 {
			for j := 0; j < k; j++ {

				v := nextInt()
				M[u-1][v-1] = 1

			}
		}

	}

	dfs()

}

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;
	v = 1;
	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 <iostream>
#include <vector>
#include <functional>

using namespace std;

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int to, T cost) : to(to), cost(cost){};
};

template <class T = int>
class Graph {
public:
    explicit Graph(int N = 0) : size(N) { path.resize(size); }
    void span(int u, int v, T cost = 1) { path[u].push_back(Edge<T>(v, cost)); }
    vector<Edge<T>> operator[](int v) const { return path[v]; }

    int size;
    vector<vector<Edge<T>>> path;
};

int main() {
    int N;
    cin >> N;
    Graph<> graph(N);
    for (int i = 0; i < N; ++i) {
        int v, k;
        cin >> v >> k;
        --v;
        for (int j = 0; j < k; ++j) {
            int sv;
            cin >> sv;
            graph.span(v, --sv);
        }
    }

    vector<int> d(N, -1), f(N, -1);
    function<int(int, int)> dfs = [&](int v, int t) -> int {
        d[v] = t;
        for (auto e : graph[v]) {
            if (d[e.to] < 0) t = dfs(e.to, t + 1);
        }
        return f[v] = ++t;
    };

    int t = 0;
    for (int v = 0; v < N; ++v) {
        if (d[v] < 0) t = dfs(v, t + 1);
    }

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

C++: #include<bits/stdc++.h>
using namespace std;
#define rep(i,a) for(int i=0;i<a;i++)
#define pd(a,n) for(int i=0;i<n;i++)cout<<a[i]<<((i==n-1)?"\n":" ")
#define pdd(a,n,m)for(int i=0;i<m;i++)pd(a,m)
#define mp make_pair
#define pb push_back
#define ll __int64
#define __int64 long long
#define P pair<int,int>
#define PP pair<P,int>

int n;
vector<int>G[1111];
int d[111];
int f[111];
int cnt;

void dfs(int x){

  d[x]=++cnt;

  rep(i,G[x].size()){
    int to=G[x][i];
    if(d[to]==0)
      dfs(to);
  }
  f[x]=++cnt;
}

int main(){
  cin>>n;
  rep(i,n){
    int k,s;
    cin>>k>>s;
    rep(j,s){
      int to;
      cin>>to;
      G[k].pb(to);
    }
    sort(G[k].begin(),G[k].end());
  }

  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>
using namespace std;
int t = 1;
int d[100], f[100];
int a[100][100];
int N;
void dfs(int cur) {
 d[cur] = t;
 t++;
 for (int i=0; i<N; i++) {
  if (a[cur][i] == 1 && d[i] == 0) {
   dfs(i);
  }
 }
 f[cur] = t;
 t++;
}

int main() {
 cin >> N;
 for (int i=0; i<N; i++) {
  for (int j=0; j<N; j++) {
   a[i][j] = 0;
  }
  d[i] = 0;
  f[i] = 0;
 }
 for (int i=0; i<N; i++) {
  int u, k;
  cin >> u >> k;
  for (int j=0; j<k; j++) {
   int v;
   cin >> v;
   a[u-1][v-1] = 1;
  }
 }
 for (int i=0; i<N; i++) {
  if (d[i] == 0) { dfs(i); }
 }
 for (int i=0; i<N; i++) {
  cout << i+1 << " " << d[i] << " " << f[i] << endl;
 }
}

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

struct TNode
{
	int Index;
	bool Visited;
	std::list<TNode*> Target;
	
	int ClockStart;
	int ClockEnd;
	
	TNode(int AIndex)
	: Index(AIndex), Visited(false), ClockStart(0), ClockEnd(0)
	{
	}
	
	void Visit(int& Clock)
	{
		if(Visited) return;
		Visited = true;
		ClockStart = Clock;
		++Clock;
		for(std::list<TNode*>::iterator It = Target.begin(); It != Target.end(); ++It){
			(*It)->Visit(Clock);
		}
		ClockEnd = Clock;
		++Clock;
	}
};

class TGraph
{
	std::vector<TNode*> FNodes;
public:
	TGraph(int Count)
	: FNodes(Count)
	{
		for(int i = 0; i < Count; ++i){
			FNodes[i] = new TNode(i + 1);
		}
	}
	
	~TGraph()
	{
		for(unsigned int i = 0; i < FNodes.size(); ++i){
			delete FNodes[i];
		}
	}
	
	void InputNode(int Index, int BranchCount)
	{
		for(int i = 0; i < BranchCount; ++i){
			int Target;
			std::cin >> Target;
			FNodes[Index - 1]->Target.push_back(FNodes[Target - 1]);
		}
	}
	
	void DepthFirstSearch()
	{
		int Clock = 1;
		FNodes[0]->Visit(Clock);
	}
	
	void OutputClocks()const
	{
		for(unsigned int i = 0; i < FNodes.size(); ++i){
			std::cout << FNodes[i]->Index      << " "
			          << FNodes[i]->ClockStart << " "
			          << FNodes[i]->ClockEnd   << std::endl;
		}
	}
};

int main()
{
	int Count;
	std::cin >> Count;
	TGraph Graph(Count);
	for(int i = 0; i < Count; ++i){
		int Index;
		std::cin >> Index;
		int BranchCount;
		std::cin >> BranchCount;
		Graph.InputNode(Index, BranchCount);
	}
	Graph.DepthFirstSearch();
	Graph.OutputClocks();
	return 0;
}

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

using namespace std;

int n;
vector<vector<int>> g; 
int time = 0;
vector<int> d, f;
 
void dfs(int node){
    time++;

    if(d[node] == 0){
        d[node] = time;
    }

    for(auto next : g[node]){
        if(d[next] == 0){
            dfs(next);
        }
    }
    
    time++;
    if(f[node] == 0){
        f[node] = time;
    }
}
    
int main(){
    
    cin >> n;

    d.assign(n + 1, 0);
    f.assign(n + 1, 0);

    g.assign(n + 1, vector<int>());

    for(int i = 0; i < n; i++)
    {
        int nod, numOut;
        cin  >> nod >> numOut;
        for(int j = 0; j < numOut; j++)
        {
            int temp;
            cin >> temp;
            g[nod].push_back(temp);
        }
    }
    
    dfs(1);

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

    return 0;
}