
object Main extends App {
  import scala.io.StdIn.{readLine}
  solve(readLine().toInt)
  class Node(val id:Int){
    private var edges:List[Node] = Nil
    def addEdge(to:Node):Unit = edges = to::edges
    def edgesTo:List[Node] = edges
  }
  def farthestNode(start:Node, memo:Array[Boolean], uft:Array[UnionFindTree]):(Int, Node) = {
    start.edgesTo.filter{n ⇒ !memo(n.id)}.map{case n ⇒
      uft(n.id).join(uft(start.id))
        memo(n.id) = true
        val res = farthestNode(n, memo, uft)
        memo(n.id) = false
        res
    } match{
      case Nil ⇒ (1, start)
      case l ⇒ {
        val (length, n) = l.maxBy{case (len, _) ⇒ len}
        (length + 1, n)
      }
    }
  }
  class UnionFindTree{
    private var mParent:Option[UnionFindTree] = None
    private def parent():UnionFindTree = mParent match{
      case None ⇒ this
      case Some(p) ⇒ p
    }
    def join(that:UnionFindTree):Unit = {
      if (!isSameUnion(that)){
        parent().mParent = Some(that.parent())
      }
    }
    def isSameUnion(that:UnionFindTree):Boolean = parent() == that.parent()
  }
  def solve(n:Int):Unit = {
    if (n == 0) return
    val nodes = Array.tabulate(101){a ⇒ new Node(a)}
    val isSearching = Array.tabulate(101){_ ⇒ false}
    val isSearched = Array.tabulate(101){_ ⇒ new UnionFindTree}
    for (_ ← 0 until n){
      val Array(a, b) = readLine().split(' ').map(_.toInt)
      nodes(a).addEdge(nodes(b))
      nodes(b).addEdge(nodes(a))
    }
    val searched = new UnionFindTree
    println((for (node ← nodes) yield {
      if (!searched.isSameUnion(isSearched(node.id))){
        searched.join(isSearched(node.id))
        isSearching(node.id) = true
        val (_, farthest) = farthestNode(node, isSearching, isSearched)
        isSearching(node.id) = false
        isSearching(farthest.id) = true
        val (res, _) = farthestNode(farthest, isSearching, isSearched)
        isSearching(farthest.id) = false
        res
      }else 0
    }).max)
    solve(readLine().toInt)
  }
}

