def fromAdjRow(xs, n)
  a = []
  1.upto(n) do |i|
    a.unshift(i) if xs[i-1] == 1
  end
  a
end

def toAdj(g, n)
  g.map do |xs|
    a = [0]*n
    unless xs[1] == 0
      xs[2..-1].each do |x|
        a[x-1] = 1
      end
    end
    a
  end
end

if __FILE__ == $0
  n = gets.to_i
  g = toAdj(n.times.map{ gets.split.map(&:to_i) }, n)

  discoveredTimeStamp = Array.new(n, 0)
  finishedTimeStamp   = Array.new(n, 0)
  discoveredVertexes  = Array.new(n, false)
  stack = [1]
  time = 1

  # stackが空になるまで探索を続ける.
  until stack.empty?
    v = stack.pop
    vs = fromAdjRow(g[v-1], n).select{ |x| !discoveredVertexes[x-1] }

    if discoveredVertexes[v-1]
      finishedTimeStamp[v-1] = time
    else
      discoveredVertexes[v-1] = true
      discoveredTimeStamp[v-1] = time
      stack.push(v)
    end
    
    vs.each{ |x| stack.push(x) }
    time+=1
  end

  1.upto(n) do |x|
    puts sprintf("%d %d %d", x, discoveredTimeStamp[x-1], finishedTimeStamp[x-1])
  end
end