import Control.Applicative
import Data.Array.IArray
import Data.Array.ST 
import Control.Monad
import Control.Monad.ST
import Debug.Trace

type Graph = Array Int [Int]
type STResult s = STArray s Int (Int, Int)
type Result = Array Int (Int, Int)

main :: IO ()
main = do
  n <- readLn :: IO Int
  ns <- replicateM n $ do
    (a:b:ns) <- getInts
    return (a, ns)
  let graph = makeGraph n ns
  mapM_ putStrLn $ res2str $ solve n graph

getInts :: IO [Int]
getInts = map read . words <$> getLine

makeGraph :: Int -> [(Int, [Int])] -> Graph
makeGraph n = accumArray (++) [] (1, n)

res2str :: Result -> [String]
res2str res = zipWith (curry f) [1..] res' 
  where
    res' :: [(Int, Int)]
    res' = map (res !) [1..(snd (bounds res))]
    f (a, (b, c)) = show a ++ " " ++
                    show b ++ " " ++ show c

solve :: Int -> Graph -> Array Int (Int, Int)
solve n graph = runST $ do
  res <- newArray (1, n) (-1, -1) :: ST s (STResult s)
--  writeArray res 1 (1, -1)
  dfs 1 2 [] res
  where
    dfs :: Int -> Int -> [Int] -> STResult s -> ST s Result
    dfs current depth ls res
      | depth /= 2 && null ls = do
          writeArray res 1 (1, depth)
          freeze res
      | otherwise = do
          cs <- filterM (\i -> do
                         (s, _) <- readArray res i
                         return (s == -1)) is
          if null cs
            then do
              (s', _) <-
                  readArray res current 
              writeArray res current (s', depth)
              dfs (head ls) (depth + 1) (tail ls) res
            else do
              let c = head cs
              writeArray res c (depth, 0)
              dfs c (depth + 1) (current:ls) res
      where
        is = graph ! current