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++: #include <bits/stdc++.h>
using namespace std;


vector<vector< int> > tstamp;
int n;
vector<vector<int> > G;
int ttime=0;

void tansaku(int i){
  if (tstamp[i][1]) return;
  ttime++;
  if (!tstamp[i][0]) tstamp[i][0] = ttime;
  for (int j=0;j<n;j++)
    if(G[i][j]) tansaku(j);
  tstamp[i][1] = ++ttime;
}




int main(){
  cin >> n;
  G.assign(n, vector<int>(n,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;
      G[u-1][v-1] = 1;
    }
  }
  tstamp.assign(n,vector<int>(2,0));
  tansaku(0);

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

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

struct Stack{
  int line[SIZE];
  int top;
  void init(){
    top = 0;
  }
  bool empty(){
    return top==0;
  }
  void push(int x){
    line[top]=x;
    top ++;
  }
  int pop(){
    if(empty()) return -1;
    top--;
    return line[top];
  }
};
struct Node
{
  vector<int> toList;
  int dt;
  int ft;
};

Stack stack; 
int t; //time

void init(vector<Node>& nodes)
{
  t=0;
  stack.init();
  stack.push(0);
  for(int i=0;i<nodes.size();i++){
    nodes[i].ft=-1;
    nodes[i].dt=-1;
  }
}
void print(vector<Node> nodes)
{
  int n=nodes.size();
  for(int i=0;i<n;i++){
    cout<<i+1<<" "<<nodes[i].ft<<" "<<nodes[i].dt<<endl;
  }
}
void dfs(vector<Node>& nodes)
{ 
  int idx=stack.pop();
  //cout<<idx+1<<":";
  if(idx>=0){
    if(nodes[idx].ft<0){
      //cout<<" find";
      t++;
      nodes[idx].ft=t;
    }
    if(nodes[idx].toList.size()<=0){
      //cout<<" toList.size==0"<<endl;
      t++;
      nodes[idx].dt=t;
      dfs(nodes);
    }
    int count=0;
    for(int i=0;i<nodes[idx].toList.size();i++){
      if(nodes[nodes[idx].toList[i]].dt<0){
	//cout<<" jumpto "<<i+1<<endl;
	count++;
	stack.push(idx);
	stack.push(nodes[idx].toList[i]);
	dfs(nodes);
      }
    }
    if(count==0 && nodes[idx].dt<0){
      //cout<<" finish"<<endl;
      t++;
      nodes[idx].dt=t;
      dfs(nodes);
    }
  }else{
    //cout<<"finish dfs"<<endl;
  }
}

int main()
{
  int n,u,k;
  cin>>n;
  vector<Node> nodes(n);
  for(int i=0;i<n;i++){
    cin>>u>>k;
    nodes[i].toList.resize(0);
    for(int j=0;j<k;j++){
      int tmp;
      cin>>tmp;
      nodes[i].toList.push_back(tmp-1);
    }
  }
  init(nodes);
  //print(nodes);

  dfs(nodes);
  print(nodes);
  return 0;
}

C++: def main():
    n = input()
    A = []
    s = []
    B = [[0,0] for i in xrange(n)]
    for i in xrange(n):
        A.append(map(int,raw_input().split()))

    color = [-1]*n
    d = [0]*n
    f = [0]*n
    
    dfs(0,0,color,d,f,A,n)

    for i in xrange(n):
        print i+1, d[i], f[i]


def dfs(u,t,color,d,f,A,n):
    t += 1
    color[u] = 0
    d[u] = t
    for i in A[u][2:]:
        if (color[i-1] == -1):
            t = dfs(i-1,t,color,d,f,A,n)
    color[u] = 1
    t += 1
    f[u] = t
    return t

if __name__ == '__main__':
    main()

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

void search(int i,int *table, int n, int *d, int *f, int *cnt){
	
	++(*cnt);
	d[i] = *cnt;
	
	for(int j=0;j<n;++j){
		if(table[i*n+j]){
			for(int k=0;k<n;++k){
				table[k*n+j] = 0;
			}
			search(j,table,n,d,f,cnt);
		}
	}
	
	++(*cnt);
	f[i] = *cnt;
}

int main() {
	int n,*table,*d,*f, cnt;
	
	cin>>n;
	table = new int[n*n];
	d = new int[n];
	f = new int[n];
	
	for(int i=0;i<n;++i){
		int u,k,v;
		cin>>u>>k;
		for(int j=0;j<k;++j){
			cin>>v;
			table[(u-1)*n+v-1]=1;
		}
	}
	cnt = 0;
	search(0,table,n,d,f,&cnt);
	
	for(int i=0;i<n;++i){
		cout<<i+1<<" "<<d[i]<<" "<<f[i]<<endl;
	}
	
	
	return 0;
}

C++: #include <bits/stdc++.h>
#define _GLIBCXX_DEBUG
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rrep(i, n) for (int i = 1; i < (n+1); ++i)
using namespace std;
using ll = long long;
const int INF = +100100100;
// typedef pair<int,int> P;

vector<vector<int>> DF(150, vector<int>(150,0));
vector<int> color(150,0);
int tt=0;
vector<int> F(150), D(150);
int n;
# define WHITE 0
# define GRAY 1
# define BLACK 2




void dfs_visit(int u){
    F[u] = ++tt;
    color[u]=GRAY;
    rep(i,n){
        if(DF[u][i]==1 && color[i]==WHITE){
            dfs_visit(i);
        }
    }
    color[u]==BLACK;
    D[u]=++tt;
}

void dfs(){
    rep(u,n){
        if(color[u]==WHITE)dfs_visit(u);
    }
}

int main(){
    cin >> n;
    vector<list<int>>  L(n);
    rep(i,n){
        int u, e;
        cin >> u>>e;
        rep(j,e){
            int v;cin>>v;--v;
            L[i].push_back(v);
        }
    }
    rep(i,n){
        rep(j,n){
            list<int>::iterator it = find(L[i].begin(),L[i].end(),j);
            if(it!=L[i].end()){
                DF[i][j]=1;
                L[i].erase(it);
            }
        }
    }
    dfs();
    rep(i,n){
        printf("%d %d %d\n",i+1,F[i],D[i]);
    }
    return 0;
}