Блог пользователя e-maxx

Автор e-maxx, 14 лет назад, По-русски

Меня недавно спрашивали про задачу о наименьшем общем предке. А именно, о поиске LCA без какого бы то ни было препроцессинга дерева, чтобы один запрос отвечался за время O(r), где r — расстояние между вершинами запроса.

Если ограничений по памяти нет, то решение придумывается почти мгновенно: будем параллельно поднимать вверх обе вершины, и помечать в двух массивах, какие вершины мы посетили по первому пути, и какие — по второму пути. Как только мы шагнём в вершину, которая есть в обоих путях — это и есть LCA.

Но такое решение требует O(n) памяти или, если использовать hash-set, то O(r) памяти.

Мне же засел в голову такой вопрос: а есть ли решение практически без дополнительной памяти, т.е. с потреблением памяти O(1)? (Разумеется, нужно сохранить ту же временную асимптотику O(r).)

Оказалось, да. Предлагаю и вам поломать голову над этой симпатичной задачкой. (Возможно, боян? Я не встречал).

Как всегда, свои варианты решения в комментариях прячьте под правками, чтобы никто случайно не прочитал решение раньше времени.

  • Проголосовать: нравится
  • +58
  • Проголосовать: не нравится

»
14 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится -18 Проголосовать: не нравится

Solution in edit.

»
14 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +7 Проголосовать: не нравится

Некоторое кривое решение в правке

»
14 лет назад, скрыть # |
Rev. 3  
Проголосовать: нравится 0 Проголосовать: не нравится

моя версия в правке (неверное, расстояние больше проходится)

»
14 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

решение в правке

»
14 лет назад, скрыть # |
Rev. 3  
Проголосовать: нравится 0 Проголосовать: не нравится

решение (примерно тоже, что у vitar, оказывается)

»
14 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +17 Проголосовать: не нравится

in edit

»
14 лет назад, скрыть # |
 
Проголосовать: нравится +39 Проголосовать: не нравится

В задаче подразумевается, что для каждой вершины мы знаем предка, хотя явно это нигде не сказано.

  • »
    »
    14 лет назад, скрыть # ^ |
     
    Проголосовать: нравится -64 Проголосовать: не нравится

    да человек хотел просто поделиться красивой задачкой, а вы накидываетесь на него...

    не срать ли как граф задается? хоть списком сыновей, хоть предками? очевидно, что как-то задается, на усмотрении автора решения — как хочет, так пусть и задает

    • »
      »
      »
      14 лет назад, скрыть # ^ |
       
      Проголосовать: нравится +13 Проголосовать: не нравится

      Так никто же не спорит. Задача хорошая и решение тоже интересно. Просто если не указать заранее, что дерево задается списком предков, то можно подумать, что подсчет для каждой вершины предка — дополнительные O(N) памяти.

    • »
      »
      »
      14 лет назад, скрыть # ^ |
       
      Проголосовать: нравится +23 Проголосовать: не нравится

      От того, как задаётся граф, задача зависит достаточно сильно. Если не указывать родителя, то задача вообще не будет иметь решения, а если, например, дополнительно указывать для каждой вершины глубину, то задача станет намного проще. Бывает, что в задаче нельзя использовать дополнительную память, но можно перезаписывать существующую (ту, в которой передаются входные данные). С таким дополнением, например, можно обойти дерево, заданное списками смежности, используя O(1) дополнительной памяти. Подобные тонкости надо обязательно указывать в условии задачи, так как они существенны для её решения.

      • »
        »
        »
        »
        14 лет назад, скрыть # ^ |
         
        Проголосовать: нравится -14 Проголосовать: не нравится

        мне почему то показалось очевидным 2 факта:

        что никакую глубину и прочую информацию не связанную напрямую с заданием графа хранить нельзя

        граф задается на усмотрение автора решения — как хочет, так пусть и задает, но только чтобы это было именно задание графа, а не еще что-либо дополнительное

        • »
          »
          »
          »
          »
          14 лет назад, скрыть # ^ |
           
          Проголосовать: нравится +5 Проголосовать: не нравится

          К сожалению, понятие "не связанную напрямую с заданием графа" трудно формализуется.

          • »
            »
            »
            »
            »
            »
            14 лет назад, скрыть # ^ |
             
            Проголосовать: нравится -20 Проголосовать: не нравится

            просто, насколько я понял, в этой задаче больше интересно решение, нежели применение...

            и если уж человек решает эту задачу, он конечно может схитрить и решить ее как-то с предподсчетом или чем-нибудь, и внушив себе, что это задание графа, но кого он обманет? себя? и вы прекрасно понимаете, что в этой фразе: “не связанную напрямую с заданием графа” я имею ввиду

        • »
          »
          »
          »
          »
          14 лет назад, скрыть # ^ |
           
          Проголосовать: нравится +8 Проголосовать: не нравится

          Ты несколько раз повторил "граф задается на усмотрение автора решения — как хочет, так пусть и задает" и тебе несколько раз ответили, в чем ты не прав. Еще раз повторяю, если мы не знаем для каждой вершины предка задача не имеет решения за O(r). Для предложеных решений необходимо знать предка каждой вершины. Если граф задан списками смежности, то нам понадобится препроцессинг за O(n) и O(n) дополнительной памяти, чтобы применить предложенные алгоритмы. Я не могу строго доказать отсутствие решения в случае если мы не знаем предков, но это очень правдоподобно. В любом случае эта задача предполагает что мы обладаем информацией о предках, потому как авторское решение использует эту информацию.

          • »
            »
            »
            »
            »
            »
            14 лет назад, скрыть # ^ |
             
            Проголосовать: нравится 0 Проголосовать: не нравится

            Ну память по факту не дополнительная. Ей можно просто затереть старую память, но О(н) времени препроцессинга никуда не девается, согласен.

            • »
              »
              »
              »
              »
              »
              »
              14 лет назад, скрыть # ^ |
               
              Проголосовать: нравится -8 Проголосовать: не нравится

              С какого перепугу ты решил перезаписывать память? Где сказано что это можно делать? Задача поставлена не формально, но додумывать то зачем. Прочитай коммент и проникнись.