import Control.Monad
import Control.Monad.State
import Data.List as L
import Data.Map as M
import Data.Maybe
import Data.Set as S

(!?) = flip M.lookup

main :: IO ()
main = do
  l1 <- getLine
  let n = read l1 :: Int
  ln <- sequence (replicate (n - 1) getLine)
  let abs = L.map (L.map read . words) ln :: [[Int]]
      (as, bs) = (L.map head abs, L.map (head . tail) abs)
      abs' = zip as bs
      (colors, edge) = execState (forM_ abs' f) (M.empty, M.empty)
      c = S.findMax $ S.unions $ M.elems colors

  print c
  forM_ abs' $ \e -> do
    print $ edge ! e

f (a, b) = do
  (colors, edge) <- get :: State ((M.Map Int (S.Set Int)), (M.Map (Int, Int) Int)) ((M.Map Int (S.Set Int)), (M.Map (Int, Int) Int))
  let uses = (fromMaybe S.empty $ colors !? a) `S.union` (fromMaybe S.empty $ colors !? b) :: S.Set Int
      c = maybe 1 fst $ S.maxView uses :: Int
      c' = maybe (c + 1) fst $ S.minView $ S.fromList [1..c] S.\\ uses

  put $ (M.insertWith S.union a (S.singleton c') $ M.insertWith S.union b (S.singleton c') colors, M.insert (a, b) c' edge)