module Main
  ( main
  )
where

import           Control.Applicative
import           Control.Monad
import           Data.List
import           Data.Array.Unboxed
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, b), (b, a)]) <$> readIntList)
  let graph = createUnweightedGraphFromList n arr
      dist1 = depthFirstSearchTree u graph
      dist2 = depthFirstSearchTree v 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)
createUnweightedEdge (from, to) = Edge { from=from, to=to, cost=1, cap=0 }
createUnweightedEdgeArrayFromList:: [(Vertex, Vertex)] -> Array Vertex Edge
createUnweightedEdgeArrayFromList arr = listArray (1, length arr) . map createUnweightedEdge $ arr

type Graph = Array Vertex (Array Int Edge)
createUnweightedGraphFromList::Int -> [(Vertex, Vertex)] -> Graph
createUnweightedGraphFromList n = listArray (1, n) . map createUnweightedEdgeArrayFromList . groupBy (\a b -> fst a == fst b) . sort

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

depthFirstSearchTreeUpdate::(Vertex, Vertex, Cost) -> Graph -> [(Vertex, Cost)]
depthFirstSearchTreeUpdate (v, p, c) graph = let newVisited = concat . map (\e -> depthFirstSearchTreeUpdate (to e, from e, c + cost e) graph) . filter (\e -> to e /= p) . elems $ graph ! v in newVisited ++ [(v, c)]
