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++: #ifdef LOCAL_BUILD
#include "pch.h"
#define DLOG(msg) cout << "#" << __LINE__ << ":" << msg << endl;
#define DLOG_V(var) \
  cout << "#" << __LINE__ << ":" << #var << " : " << var << endl;
#else
#include <bits/stdc++.h>
#define DLOG(msg)
#define DLOG_V(var)
#endif
using namespace std;

constexpr auto no_value = numeric_limits<uint64_t>::max();

struct GraphParser {
  GraphParser(vector<vector<int>>& edges_)
      : edges(edges_), start(edges.size(), 0), end(edges.size(), 0) {
  }

  void run() {
    t = 0;
    for (size_t i = 0; i < edges.size(); ++i) {
      if (!start[i]) {
        recur(i);
      }
    }
  }

  void run_stack() {
    t = 0;
    for (size_t j = 0; j < edges.size(); ++j) {
      if (start[j]) continue;
      start[j] = ++t;
      st.push(make_pair(j, 0));
      while(!st.empty()) {
        auto& p = st.top();
        auto v = p.first;
        auto& i = p.second;
        if (i < edges[v].size()) {
          auto v2 = edges[v][i++];
          if (!start[v2]) {
            start[v2] = ++t;
            st.push(make_pair(v2, 0));
          }
        } else {
          end[v] = ++t;
          st.pop();
        }
      }
    }
  }

  vector<vector<int>>& edges;
  vector<int> start;
  vector<int> end;
  stack<pair<int, size_t>> st;
  int t;

 private:
  void recur(int cur) {
    if (start[cur]) {
      return;
    }
    start[cur] = ++t;
    for (auto&& e : edges[cur]) {
      recur(e);
    }
    end[cur] = ++t;
  }
};

int main() {
  int n;
  cin >> n;
  vector<vector<int>> edges(n, vector<int>());
  for (int i = 0; i < n; ++i) {
    int u;
    int k;
    cin >> u >> k;
    edges[u - 1].reserve(k);
    for (int j = 0; j < k; ++j) {
      int v;
      cin >> v;
      edges[u - 1].push_back(v - 1);
    }
  }

  GraphParser p(edges);
  p.run_stack();
  for (int i = 0; i < n; ++i) {
    cout << (i + 1) << " " << p.start[i] << " " << p.end[i] << endl;
  }
}

C++: // -*- mode:c++; coding:utf-8; c-basic-offset:2; -*-
// ALDS1_11_B: Depth First Search

#include <algorithm>
#include <cstdio>
#include <stack>
#include <utility>

using uint = unsigned int;

class Graph {
  const uint n_;
  uint* const g_;
  std::pair<uint, uint>* const visited_;
  uint time_;
  
public:
  Graph(uint n) : n_(n),
                  g_(new uint[(n_*n_)]),
                  visited_(new std::pair<uint, uint>[n_])
  {
    std::fill(g_, g_+(n_*n_), 0u);
  }

  ~Graph()
  {
    delete[] g_;
    delete[] visited_;
  }
  
  uint* operator [](uint i) const { return g_+(n_*i); }

  std::pair<uint, uint>* visited() const { return visited_; }

  void dfs()
  {
    init_visited();
    for (auto i = 0u; i < n_; ++i) {
      inner_dfs(i);
    }
  }

private:
  void init_visited()
  {
    time_ = 0u;
    for (auto i = 0u; i < n_; ++i) {
      visited_[i].first = 0u;
    }
  }

  void inner_dfs(uint i)
  {
    if (visited_[i].first) {
      return;
    }
    visited_[i].first = time_++;
    for (auto j = 0u; j < n_; ++j) {
      auto k = (*this)[i][j];
      if (k) {
        inner_dfs(j);
      }
    }
    visited_[i].second = time_++;
  }
};

int main()
{
  uint n;
  std::scanf("%u", &n);

  Graph g(n);

  uint u, k, v;
  for (auto i = 0u; i < n; ++i) {
    std::scanf("%u %u", &u, &k);
    for (auto j = 0u; j < k; ++j) {
      std::scanf("%u", &v);
      g[u-1][v-1] = 1;
    }
  }

  g.dfs();
  auto visited = g.visited();
  for (auto i = 0u; i < n; ++i) {
    std::printf("%u %u %u\n", i+1, visited[i].first+1, visited[i].second+1);
  }
}

// eof

C++: #include <iostream>
#include <string>
#include <vector>
using namespace std;
typedef long long ll;
const int INF = 1<<30; 
const int MOD = 1e9 + 7;
const int MAX_N = 150;
int G[MAX_N][MAX_N], found[MAX_N], finished[MAX_N];
int Time, N;
void dfs(int u)
{
    Time++;
    found[u] = Time;
    for(int nextV = 1; nextV <= N; nextV++)
    {
        if(found[nextV] || G[u][nextV] == 0) continue;
        dfs(nextV);
    }
    Time++;
    finished[u] = Time;
}
void init()
{
    Time = 0;
    for(int i = 0; i <= N; i++)
    {
        found[i] = 0;
        finished[i] = 0;
    }
    for(int i = 0; i <= N; i++) for(int j = 0; j <= N; j++) G[i][j] = 0;
}
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> N;
    init();
    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][v] = 1;
        }
    }
    int u = 1;
    while(u <= N)
    {
        if(found[u] == 0) dfs(u);
        u++;
    }
    for(int v = 1; v <= N; v++)
    {
        cout << v << " " << found[v] << " " << finished[v] << endl;
    }
    return 0;
}

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

void solve(){
  int n; cin >> n;
  vector<vector<int> > v(n + 1, vector<int>(n + 1, 0));
  for(int i = 0; i < n; i++){
    int u, k; cin >> u >> k;
    for(int j = 0; j < k; j++){
      int x; cin >> x;
      v[u][x] = 1;
    }
  }
  vector<int> d(n + 1), f(n + 1), c(n + 1, 0);
  stack<int> s;
  int t = 0;
  for(int j = 1; j <= n; j++){
    if(c[j] == 0){
      s.push(j);
      d[j] = ++t;
      c[j] = 1;
      while(s.size() != 0){
        t++;
        int x = s.top();
        int i;
        for(i = 1; i <= n; i++){
          if(v[x][i] == 1 && c[i] == 0){
            d[i] = t;
            c[i] = 1;
            s.push(i);
            break;
          }
        }
        if(i == n + 1){
          f[x] = t;
          s.pop();
        }
      }
    }
  }
  for(int i = 1; i <= n; i++){
    cout << i << " " << d[i] << " " << f[i] << endl;
  }
  return;
}

int main(){
  solve();
  return 0;
}