Алгоритм Шибера-Вишкина — различия между версиями
Строка 74: | Строка 74: | ||
}} | }} | ||
− | Каждое значение <tex>\operatorname{inlabel} v</tex> соответствует вершине в полном двоичном дереве <tex>B</tex> высоты <tex>h=\lceil\log_2 n\rceil</tex>. В дереве на одном наборе вершин будет построено два набора ребер: ''каркасные'' и ''основные''. Для каждой вершины <tex>v \in V(B)</tex> с уровня, кроме последнего, будут каркасные ребра <tex>v\to2v</tex> и <tex>v\to2v+1</tex>. Таким образом, вершины в <tex>B</tex> будут занумерованы в инфиксном порядке обхода по каркасным ребрам: сначала обрабатывается левое поддерево, потом {{---}} вершина, потом {{---}} правое | + | Каждое значение <tex>\operatorname{inlabel} v</tex> соответствует вершине в полном двоичном дереве <tex>B</tex> высоты <tex>h=\lceil\log_2 n\rceil</tex>. В дереве на одном наборе вершин будет построено два набора ребер: ''каркасные'' и ''основные''. Для каждой вершины <tex>v \in V(B)</tex> с уровня, кроме последнего, будут каркасные ребра <tex>v\to2v</tex> и <tex>v\to2v+1</tex>. Таким образом, вершины в <tex>B</tex> будут занумерованы в инфиксном порядке обхода по каркасным ребрам: сначала обрабатывается левое поддерево, потом {{---}} вершина, потом {{---}} правое поддерево. В <tex>B</tex> будет основное ребро между вершинами <tex>\operatorname{inlabel} v</tex> и <tex>\operatorname{inlabel} u</tex>, если в <tex>T</tex> есть ребро <tex>v\to u</tex>. Корень имеет номер <tex>1</tex>. Будем говорить, что вершина <tex>u \in B</tex> лежит в поддереве вершины <tex>u \in B</tex> (<tex>u \in S(v)</tex>), если от <tex>v</tex> есть путь до <tex>u</tex> по каркасным ребрам. |
{{Утверждение | {{Утверждение | ||
Строка 97: | Строка 97: | ||
#<tex>path \leftarrow 2^i \lfloor\frac{(\operatorname{ascendant} x) \wedge (\operatorname{ascendant} y)}{2^i}\rfloor</tex> | #<tex>path \leftarrow 2^i \lfloor\frac{(\operatorname{ascendant} x) \wedge (\operatorname{ascendant} y)}{2^i}\rfloor</tex> | ||
#<tex>LCA(\operatorname{inlabel} x, \operatorname{inlabel} y) \leftarrow \lfloor\frac12(path \oplus (path - 1))\rfloor + 1</tex> | #<tex>LCA(\operatorname{inlabel} x, \operatorname{inlabel} y) \leftarrow \lfloor\frac12(path \oplus (path - 1))\rfloor + 1</tex> | ||
− | |proof=<tex>x</tex> и <tex>y</tex> {{---}} вершины в <tex>B</tex>. Биты в их записи задают задают их местоположение в дереве. | + | |proof=<tex>\operatorname{inlabel} x</tex> и <tex>\operatorname{inlabel} y</tex> {{---}} вершины в <tex>B</tex>. Биты в их записи задают задают их местоположение в дереве. |
Ноль {{---}} спуститься влево, единица {{---}} спуститься вправо или остаться здесь. Значит, наиболее значимый бит побитового исключающего или их номеров даст глубину, на которой пути до этих вершин начинают расходиться. Это и хранится в <tex>i</tex>. | Ноль {{---}} спуститься влево, единица {{---}} спуститься вправо или остаться здесь. Значит, наиболее значимый бит побитового исключающего или их номеров даст глубину, на которой пути до этих вершин начинают расходиться. Это и хранится в <tex>i</tex>. | ||
Версия 21:36, 23 июня 2012
Алгоритм Шибера-Вишкина применяется для нахождения наименьшего общего предка двух вершин в дереве. Он использует
времени на подготовку и затем отвечает на каждый запрос за .Содержание
Идея алгоритма
Основная идея алгоритма следующая.
- Если бы дерево, в котором нужно искать было бы простым путем, можно было бы найти просто взяв ту вершину, которая находится в дереве ближе к корню.
- Если дерево — полное двоичное дерево высоты , то можно сопоставить каждой вершине битовый вектор длиной (целое число от до ) и с помощью битовых операций над этими векторами найти
Тогда, представив данное дерево как полное двоичное дерево, в некоторых вершинах которого находится простой путь, можно научиться искать
в нем за .Подготовка
Определение: |
| — входное дерево с вершинами. Для него нужно отвечать на запросы .
Перенумеруем вершины в порядке префиксного обхода дерева: сначала обрабатывается текущая вершина, затем — поддеревья.
Пусть — такой порядок обхода.
Обозначим за
количество вершин в поддереве вершины .Утверждение: |
Пусть . Тогда
|
По определению , вершин из поддерева образуют отрезок натуральных чисел длиной . Так как этот отрезок начинается с , то лежит в отрезке . |
Покроем дерево путями. А именно, сопоставим каждой вершине
число такое, что прообраз каждого в связен и является простым путем от какой-то вершины вниз до листа.Утверждение: |
В качестве можно выбрать , кратное максимальной степени двойки, где . |
Пусть , — максимально. Пусть есть вершина такая, что . Так как в отрезке, соответствующем вершине есть два числа, кратных , то там есть и число, кратное . Но тогда выбран неверно. Значит, в поддереве есть только одна такая вершина , что .Рассмотрим два случая. Первый случай Других таких вершин , что дает такую же степень двойки, нет. Значит, во всех поддеревьях значения отличаются от .Второй случай Получили, что прообраз , . Так как в поддереве представлены все -ы из отрезка , то рассмотрим того непосредственного потомка вершины , что . Тогда, так как степень двойки у максимальна, по утверждению в начале доказательства, других вершин с такой же степенью двойки нет, то . Так как отрезки, соответствующие поддеревьям сыновей, не пересекаются, не найдется другого — потомок , что в поддереве есть вершина с такой же степенью двойки. Значит, все вершины , у которых находятся в поддереве . в вершине или обрывается, или продолжается вниз ровно в одного потомка. Значит, прообраз — простой путь из какой-то вершины вниз в , что и требовалось доказать. |
Утверждение: |
, где |
Посмотрим на . Посмотрим на позицию самго значимого единичного бита в .Так как в там еще , а в — уже единица, то в отрезке есть число, кратное .Докажем, что нет чисел, кратных . Пусть такое число нашлось. Тогда -й бит менялся хотя бы два раза, а значит, менялся -й бит. А значит, самый значащий отличающийся бит в и в больше, чем -й.Заметим, что функция просто выделяет номер самого значашего единичного бита.Функция Чтобы получить из отрезка число, кратное обнуляет все биты младше -го. , будучи уверенными, что оно там есть, достаточно обнулить битов в правой границе отрезка. |
Каждое значение
соответствует вершине в полном двоичном дереве высоты . В дереве на одном наборе вершин будет построено два набора ребер: каркасные и основные. Для каждой вершины с уровня, кроме последнего, будут каркасные ребра и . Таким образом, вершины в будут занумерованы в инфиксном порядке обхода по каркасным ребрам: сначала обрабатывается левое поддерево, потом — вершина, потом — правое поддерево. В будет основное ребро между вершинами и , если в есть ребро . Корень имеет номер . Будем говорить, что вершина лежит в поддереве вершины ( ), если от есть путь до по каркасным ребрам.Утверждение: |
Если в есть ребро , то в :
Другими словами, все основные ребра направлены вниз. |
Посчитаем для каждого
множество всех его потомков в по основным ребрам. Заметим, что для хранения одного потомка достаточно хранить только его высоту в дереве. Чтобы восстановить его значение, нужно просто подняться на вверх от вершины . Поэтому, все это множество можно уместить в целое число: -й бит будет единицей, если есть потомок на высоте . Назовем это число, отвечающее множеству предков, .В дальнейшем
поможет в поиске . Также, нам понадобится еще следующая информация. — самая не глубокая вершина такая, что . — глубина вершины в .Обработка запроса
Пусть
, — вершины в исходном дереве которых необходимо найти. Если , то они принадлежат одному простому пути, а следовательно ответом на запрос является , если , и , в противном случае. Теперь рассмотрим случай, когда , то есть и принадлежат разным простым путям. Найдем .Сначала найдем
по каркасным ребрам. Для этого вомпользуемся посчитанными значениями .Утверждение: |
Следующие вычисления позволяют найти :
|
и — вершины в . Биты в их записи задают задают их местоположение в дереве. Ноль — спуститься влево, единица — спуститься вправо или остаться здесь. Значит, наиболее значимый бит побитового исключающего или их номеров даст глубину, на которой пути до этих вершин начинают расходиться. Это и хранится в . Значит, мы нашли Взяв побитовое и по каркасным ребрам. Однако, могло случиться так, что по основным ребрам, поиском которого мы занимаемся, находится выше (он не может находиться ниже или в стороне, так как все основные ребра направлены вниз). и , в старших единичных битах мы получим путь от корня по основным ребрам до этих вершин. При этом, про те биты, которые отвечают за уровни ниже , ничего не известно. Поэтому, нужно их обнулить. Умножение и деление на обнулят ненужные биты. После этого, для нахождения по основным ребрам, нужно найти в наименее значимый единичный бит. Формула имеено это и делает. |
После этих действий нами был получен путь, в котором находится ответ. Осталось посмотреть на точки входа
и на путь . Это можно сделать с помощью посчитанной функции : найти , где — вершина предпоследнего пути в пути. Тогда, поднявшись от нее на один вверх по начальному дереву, получим искомую точку входа.Имея две точки входа, можно, как и в первом случае, сравнить их по высоте и выбрать более высокое из них.
Оценка сложности
Построение
Подсчет каждого из массивов занимает
. Это можно сделать, например, обходом в глубину.Запрос
Здесь нужно сделать
действий для ответа на запрос.