import scala.io.StdIn.{readInt, readLine};
object Main {
    def main(args: Array[String]): Unit = {
        val n = readInt;
        val g = new Graph(n);
        (0 until n).foreach { i => 
            readLine.split(" ").map(_.toInt).toList match {
                case src :: d :: dst => g.add(src, dst);
                case _ => ()
            }
        }
        g.depthFirstSearch.zipWithIndex.foreach { e => e match {
                case ((discover, finish), node) => println("%d %d %d".format(node + 1, discover, finish));
            }
        }
    }
}
class Graph(n: Int) {
    val size = n + 1;
    val matrix = Array.ofDim[Int](size, size);
    def add(src: Int, dsts: Seq[Int]): Unit = if (src > 0 && src < size) {
        dsts.foreach { d => if (d > 0 && d < size) matrix(src)(d) = 1};
    }
    def dump(): Unit = matrix.slice(1, size).foreach { a => println(a.slice(1, size).mkString(" "))}
    def depthFirstSearch(): Array[(Int, Int)] = {
        val status = new Array[(Int, Int)](size);
        def go(curr: Int, discoverTime: Int): Int = {
            if (curr >= size) {
                discoverTime;
            } else {
                status(curr) = (discoverTime, -1);
                val finishTime = 1 + (1 until size).foldLeft(discoverTime) { (time, i) => 
                    if (matrix(curr)(i) == 1 && status(i) == null) go(i, time + 1) else time;
                };
                status(curr) = (discoverTime, finishTime);
                finishTime;
            }
        } 
        (1 until size).foldLeft(0) { (time, i) => 
            if (status(i) == null) go(i, time + 1)else time;
        }
        status.slice(1, size);
    }
}
