Go: package main

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

/***************************************************************
stackによる深さ優先探索を実装する。
***************************************************************/

const (
	N     = 100
	WHITE = 0
	GRAY  = 1
	BLACK = 2
)

var (
	n            int
	Adj          [N][N]int
	statusColor  [N]int
	discoverTime [N]int
	finishTime   [N]int
	clock        int
	nt           [N]int
)

/***************************************************************
Stackの定義:
- field
	container: ノードの格納されたスライス
	sp: スタックポインタ
- method
	size(): スタックに積まれているノードの個数を返す
	top(): スタックの一番上に積まれているノードを返す
	isEmpty(): スタックが空かどうかを返す
	pop(): スタックの要素をポップし削除する
	push(): スタックに要素を積む
***************************************************************/

type Stack struct {
	container []int
	sp        int
}

func (s *Stack) size() int {
	return len(s.container)
}

func (s *Stack) top() int {
	return s.container[s.sp]
}

func (s *Stack) isEmpty() bool {
	return s.sp == 0
}

func (s *Stack) pop() int {
	_pop := func() {
		s.container = s.container[:len(s.container)-1]
	}
	defer _pop()
	if s.isEmpty() {
		panic("There is no elements in stack!")
	}
	s.sp--
	return s.container[s.sp]
}

func (s *Stack) push(n int) {
	s.sp++
	s.container[s.sp] = n
}

func next(u int) int {
	for v := nt[u]; v < n; v++ {
		nt[u] = v + 1
		if Adj[u][v] == 1 {
			return v
		}
	}
	return -1
}

func _DFS(target int) {
	for i := 0; i < n; i++ {
		nt[i] = 0
	}
	stack := new(Stack)
	stack.container = make([]int, N+1)
	stack.push(target)
	statusColor[target] = GRAY
	clock++
	discoverTime[target] = clock
	for !stack.isEmpty() {
		u := stack.top()
		v := next(u)
		if v != -1 {
			if statusColor[v] == WHITE {
				statusColor[v] = GRAY
				clock++
				discoverTime[v] = clock
				stack.push(v)
			}
		} else {
			stack.pop()
			statusColor[u] = BLACK
			clock++
			finishTime[u] = clock
		}
	}
}

func DFS() {
	for i := 0; i < n; i++ {
		statusColor[i] = WHITE
		nt[i] = 0
	}
	clock = 0
	for i := 0; i < n; i++ {
		if statusColor[i] == WHITE {
			_DFS(i)
		}
	}
	for i := 0; i < n; i++ {
		fmt.Printf("%d %d %d\n", i+1, discoverTime[i], finishTime[i])
	}
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	scanner.Scan()
	n, _ = strconv.Atoi(scanner.Text())
	for i := 0; i < n; i++ {
		for j := 0; j < n; j++ {
			Adj[i][j] = 0
		}
	}
	for i := 0; i < n; i++ {
		scanner.Scan()
		u, _ := strconv.Atoi(scanner.Text())
		scanner.Scan()
		k, _ := strconv.Atoi(scanner.Text())
		u--
		for j := 0; j < k; j++ {
			scanner.Scan()
			v, _ := strconv.Atoi(scanner.Text())
			v--
			Adj[u][v] = 1
		}
	}

	DFS()
}

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;
}

C++: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
constexpr int di[] = {0, 1, 0, -1}, dj[] = {1, 0, -1, 0};
#define rep(i, n) for (int i = 0; i < n; i++)
#define repr(i, n) for (int i = n; i >= 0; i--)
#define sort(v) sort((v).begin(), (v).end())
#define sortr(v) sort((v).rbegin(), (v).rend())
#define all(v) (v).begin(), (v).end()
#define max 100005
#define nil -1

vector<vector<int>> g;
int t=0;
vector<int> d,f;
vector<bool> visited;

void dfs(int u){
    visited[u]=true;
    t++;
    d[u]=t;
    for(auto to:g[u]){
        if(!visited[to]){
            dfs(to);
        }
    }
    t++;
    f[u]=t;
}

int main() {
  int  n,u,k,v;
  cin>>n;
    g.resize(n);
    d.resize(n);
    f.resize(n);
    visited.resize(n, false);
  rep(i,n){
      cin>>u>>k;
      u--;
      for(int j=0;j<k;j++){
          cin>>v;
          v--;
          g[u].push_back(v);
        }
    }
    rep(i,n){
        if(!visited[i]){
            dfs(i);
        }
    }
    rep(i,n){
        cout<<i+1<<" "<<d[i]<<" "<<f[i]<<endl;
    }
  return 0;
}

C++: #include<iostream>
#include<stdio.h>

#define N 100
#define WHITE 0
#define GRAY 1
#define BLACK 2

int n;
int M[N][N];
int color[N];
int d[N];
int f[N];
int tt;

//再帰関数によるDFS
void dfs_visit(int u)
{
    int v;
    color[u]=GRAY;
    d[u]=++tt;//最初の訪問

    for(v=0;v<n;v++)
    {
        if(M[u][v]==0) continue;
        if(color[v]==WHITE)
        {
            dfs_visit(v);
        }
    }

    //探索終了の記録
    //再帰初期のuほど遅く探索が終了する
    color[u]=BLACK;
    f[u]=++tt;
}

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

    for(u=0;u<n;u++)
    {
        //未訪問のuを始点としてとしてDFS
        if(color[u]==WHITE) dfs_visit(u);
    }
    for(u=0;u<n;u++)
    {
        printf("%d %d %d\n",u+1,d[u],f[u]);
    }
}


int main()
{
    int u,v,k,i,j;

    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)M[i][j]==0;
    }

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

    dfs();
    return 0;
}