import Control.Monad
import Data.List

main :: IO ()
main = do
  n <- readLn
  gs <- replicateM n $ fmap (map read . words) getLine :: IO [[Int]]
  solve gs

type Graph = [[Int]]

solve gs = printResult . count . reverse $ stackDFS (toAdjMatrix gs) [0] []

printResult :: ([Int], [Int]) -> IO ()
printResult (fv, ds) = forM_ [0..(length fv - 1)] $ \i -> do
  putStrLn   . unwords . map show $ [i + 1, fv !! i, ds !! i]

stackDFS :: Graph -> [Int] -> [Int] -> [Int]
stackDFS _ [] vs = vs
stackDFS gs (s:ss) vs = if unfinished == []
                        then stackDFS gs ss (s:vs)
                        else stackDFS gs (v:s:ss) (s:vs)
  where
    n = length gs
    edges = gs !! s
    unfinished = [i | i <- [0..(n - 1)], edges !! i == 1, not(elem i vs)]
    v = head unfinished

count :: [Int] -> ([Int], [Int])
count path = (firstVisit path, doneSearch path)
  where
    firstVisit :: [Int] -> [Int]
    firstVisit path = map findFirst [0..m]
      where
        m = maximum path
        findFirst :: Int -> Int
        findFirst i = let Just j = elemIndex i path
                      in j + 1

    doneSearch :: [Int] -> [Int]
    doneSearch path = map (length path + 2 - ) . firstVisit . reverse $ path

toAdjMatrix :: Graph -> Graph
toAdjMatrix gs = scanColumn gs $ length gs
  where
    scanColumn :: Graph -> Int -> Graph
    scanColumn [] _ = []
    scanColumn (x:xs) n = (makeRow x n) : (scanColumn xs n)

    makeRow :: [Int] -> Int -> [Int]
    makeRow (u:k:vs) n = [if x `elem` vs then 1 else 0 | x <- [1..n]]

