{-# LANGUAGE MultiWayIf #-}

module Main
  ( main
  )
where

import           Control.Applicative
import           Control.Monad
import           Data.List
import qualified Data.Vector                   as V
import           Data.Char
import           Data.Bits
import qualified Data.ByteString.Char8         as BS
import           Data.Maybe

parse = fst . fromJust
parseInt = parse . BS.readInt
parseInteger = parse . BS.readInteger
readInt = parseInt <$> BS.getLine
readInteger = parseInteger <$> BS.getLine
readIntList = map parseInt . BS.words <$> BS.getLine

main = do
  [n, u, v] <- readIntList
  arr       <- concat <$> replicateM
    (n - 1)
    ((\[a, b] -> [(a - 1, b - 1), (b - 1, a - 1)]) <$> readIntList)
  let
    graph    = createUnweightedGraphFromList arr
    dist1    = treeDepthFirstSearch (u - 1) graph
    dist2    = treeDepthFirstSearch (v - 1) graph
    farthest = maximum . map snd . filter (\(a, b) -> a < b) $ zip dist1 dist2
  print $ farthest - 1

type Vertex = Int
type Cost = Int
type Capacity = Int

data Edge = Edge { from :: Vertex, to :: Vertex, cost :: Cost, cap :: Capacity } deriving (Eq, Ord, Show)
newUnweightedEdge (from, to) = Edge { from = from, to = to, cost = 1, cap = 0 }
createUnweightedEdgeVectorFromList :: [(Vertex, Vertex)] -> V.Vector Edge
createUnweightedEdgeVectorFromList = V.fromList . map newUnweightedEdge

type Graph = V.Vector (V.Vector Edge)
createUnweightedGraphFromList :: [(Vertex, Vertex)] -> Graph
createUnweightedGraphFromList =
  V.fromList
    . map createUnweightedEdgeVectorFromList
    . groupBy (\a b -> fst a == fst b)
    . sort

treeDepthFirstSearch :: Vertex -> Graph -> [Cost]
treeDepthFirstSearch src =
  map snd . sort . updateTreeDepthFirstSearch [(src, 0, src, 0)]

updateTreeDepthFirstSearch
  :: [(Vertex, Int, Vertex, Cost)] -> Graph -> [(Vertex, Cost)]
updateTreeDepthFirstSearch ((v, i, p, c) : xs) g =
  let edge       = (g V.! v) V.!? i
      newVisited = case edge of
        Nothing -> updateTreeDepthFirstSearch xs g
        Just e
          | to e == p -> updateTreeDepthFirstSearch ((v, i + 1, p, c) : xs) g
          | otherwise -> updateTreeDepthFirstSearch
            ((to e, 0, v, c + cost e) : (v, i + 1, p, c) : xs)
            g
      additional = if i == 0 then [(v, c)] else []
  in  newVisited ++ additional
updateTreeDepthFirstSearch [] _ = []
