Изменения

Перейти к: навигация, поиск

Деревья Эйлерова обхода

1305 байт добавлено, 19:44, 4 сентября 2022
м
rollbackEdits.php mass rollback
==ВведениеЗадача о динамической связности=={{Задача|definition = Для решения задачи о динамической связности (англ.''dynamic connectivity problem'') требуется выполнение следующих операцийдинамически изменяющегося дерева выполнить следующие запросы:* '''<tex>\mathrm{link(u, w)}</tex>''' {{---}} добавить ребро <tex>(u, w) </tex> (при условии, что вершины <tex>u </tex> и <tex>w </tex> принадлежат разным деревьям),* '''<tex>\mathrm{cut(u, w)}</tex>''' {{---}} разрезать ребро <tex>(u, w) </tex> (при условии, что ребро <tex>(u, w) </tex> принадлежит дереву),* '''<tex>\mathrm{isConnected(u, w)}</tex>''' {{---}} определить принадлежат ли вершины <tex>u </tex> и <tex>w </tex> одной компоненте связности.}}
'''Дерево Для решения поставленной задачи будем представлять дерево в виде его [[Эйлеровость графов|эйлерова обхода''' графа]], а затем будем работать с [[Эйлеровость графов|эйлеровым обходом]] (англ.''Euler tour tree'') {{---}} способ представления динамического дерева, позволяющий этого графа. Это позволит выполнять указанные операции запросы за <tex>O(\log n)</tex>.
==Представление деревьев в виде эйлерова графа==
<br>
==Свойство эйлерова обхода== Представим дерево в виде последовательности вершин, посещеннных посещенных в порядке эйлерова обхода , начиная с корнем в вершине вершины <tex>a</tex>.
[[Файл:Tour1.png|thumb|320px|center]]
При этом последовательность вершин между первым и последним вхождением вершины <tex>h</tex> дает эйлеров обход поддерева с корнем <tex>h</tex>.
[[Файл:Tour2.png|thumb|320px|center]]
==Операцииc эйлеровыми обходами== ===Изменение корня дерева (переподвешивание)===Дано дерево с корнем в вершине <tex>a</tex>. Требуется переподвесить его к вершине <tex>h</tex>. [[Файл:Tour13.png |thumb|320px|center]] Для переподвешивания (англ. ''rerooting'') необходимо:*Разбить эйлеров обход на три части <tex>S1 </tex>, <tex>H</tex>, и <tex>S2 </tex>, где <tex>H</tex> состоит из вершин между первым и последним вхождением нового корня <tex>h</tex>.*Удалить первую вершину в <tex>S1 </tex>.*Соединить в следующем порядке: <tex>H</tex>, <tex>S2 </tex>, <tex>S1 </tex>.*Добавить <tex>\{h\}</tex> в конец последовательности. В результате получим: [[Файл:Proba.png |center]]
===Добавление ребра===
[[ФайлДля добавления ребра <tex>(c, g)</tex>:Link11*Выберем любое вхождение вершины <tex>c</tex> в эйлеров обход дерева <tex>T1</tex>.*Разрежем эйлеров обход <tex>T1</tex> на две части:*: <tex>A1</tex> {{---}} часть обхода до выбранного вхождения вершины <tex>c</tex>, включая ее.*: <tex>A2</tex> {{---}} часть обхода после выбранного вхождения вершины <tex>c</tex>, включая ее.*Аналогично, выберем любое вхождение вершины <tex>g</tex> в эйлеров обход дерева <tex>T2</tex> и разрежем его на две части <tex>B1</tex> и <tex>B2</tex>.*Соберем результирующий эйлеров обход в порядке <tex>A1, B2, B1</tex> (без первой повторяющейся вершины), <tex>A2</tex>.png |thumb|400px|center]]
Для связывания Чтобы быстро находить место, где разрезать эйлеровы обходы деревьев <tex>T1 </tex> и <tex>T2</tex>, где будем хранить эйлеровы обходы в двоичных деревьях поиска. Ключом вершины для построения дерева поиска будет время посещения этой вершины эйлеровым обходом.Для каждой вершины дерева <tex>c\in (T1\ </tex>, а <tex>g\in T2\)</tex> добавлением ребра <tex>\{cбудем хранить указатель на вершину в дереве поиска, g\} \</tex> необходимо:*Переподвесить дерево <tex>T1</tex> к вершине <tex>c</tex>которая соответствует вхождению вершины дерева в эйлеров обход.*Переподвесить дерево Тогда за <tex>T2O(1)</tex> переходим от вершины дерева к вершине дерева поиска, по которой за <tex>g</tex>.*Соединить получившиеся эйлеровы обходы.*Добавить <tex>\{cO(\}log n)</tex> в конец последовательностиможно будет разделить дерево поиска на две части.
[[Файл:Link2Link22.png|thumb|400px |center]] В результате получим: [[Файл:Link3|Рис.1a Исходный лес <br>Рис.1b Эйлеровы обходы деревьев<br> Рис.png|center1с Двоичные деревья поиска для хранения эйлеровых обходов <br> Рис.1d Результирующий эйлеров обход]]
===Разрезание ребра===
[[Файл:Cut1.png|thumb|350px|center]]
 
Для разбиения дерева на два поддерева путем разрезания ребра <tex>\{g, j\} \</tex> (если оно существует) необходимо:
*Переподвесить дерево к вершине <tex>g</tex>.
*Разделить дерево на части <tex>E1, V, E2</tex>, где <tex>V</tex> отрезок между первым и последним вхождением вершины <tex>j</tex>.
*Эйлеров обход первого поддерева образуется соединением <tex>E1</tex> и <tex>E2</tex>, с удалением повторного <tex>\{g\}</tex> в месте их соединения.
*Эйлеров обход второго поддерева образует <tex>V</tex>.
 
[[Файл:Cut2.png|thumb|350px|center]]
 
В результате получим:
[[Файл:Cut3.png|thumb|350px|center]]
 
==Реализация структуры==
 
{{Задача
|definition = Определить структуру данных для хранения эйлеровых обходов деревьев для наиболее эффективного выполнения указанных операций.
}}
При представлении деревьев Для удаления ребра <tex>(g, j)</tex>:*Найдем в виде их эйлерова обхода выполнение каждой операции эйлеровом обходе дерева <tex>T</tex> две пары посещений концов удаляемого ребра <tex>\mathrm{link}g,j</tex> и <tex>\mathrm{cut}j,g</tex> сводится к , которые соответствуют прохождениям по ребру <tex>O(1g, j)</tex> соединений в дереве <tex>T</tex>.*Разрежем эйлеров обход дерева по этим парам на три части: <tex>A1, A2, A3</tex>.*Соединив <tex>A1</tex> и разбиений отрезков в последовательности вершин эйлерова обхода<tex>A3</tex> (без повторяющейся первой вершины), получим эйлеров обход первого дерева, а <tex>A2</tex> дает эйлеров обход второго дерева.
Рассмотрим следующие структуры данных Чтобы быстро находить места в эйлеровом обходе, которые соответствуют прохождению удаляемого ребра в дереве, будем для каждого ребра в дереве хранить ссылку на те места эйлерова обхода, где последовательно посещаем концы удаляемого ребра.Так, для определения времени выполнения разбиения и соединения последовательностейребра <tex>(g, j)</tex> храним ссылки на узлы дерева поиска, а также определение принадлежности вершин одной компоненте связностисоответствующие парам посещений концов этого ребра.
===Связные списки===[[Файл:Link23.png |thumb|400px|center|Рис.1a Исходное дерево <br>Рис.1b Эйлеров обход исходного дерева<br> Рис.1с Двоичное дерево поиска для хранения эйлерового обхода <br> Рис.1d Эйлеровы обходы получившихся деревьев]]
[[Файл:Linked lists===Проверка на связность===Для того, чтобы проверить, лежат ли две вершины в одном дереве, достаточно подняться от вхождения каждой вершины в эйлеров обход (ссылку на которое мы храним) до корня дерева поиска, хранящего этот эйлеров обход.png |center]]
==Способы реализации структуры==
Каждое разбиение и соединение последовательностей требует <tex>O(1)</tex>.===Сбалансированное дерево поиска===
Для каждой вершины будем Будем хранить указатели на первое и последнее вхождение вершины последовательность вершин эйлерова обхода в виде сбалансированного двоичного дерева поиска, например, в последовательностьвиде [[Красно-черное дерево|красно-черного дерева]]. Тогда возможно определять первое и последнее вхождение При построении дерева ключом вершины будет время посещения этой вершины за <tex>O(1)</tex>эйлеровым обходом.
Однако,используя [[Список|двусвязные списки]] определение принадлежности вершин одной компоненте связности занимает Операции объединения и разделения красно-черных деревьев выполняется за <tex>O(\log n)</tex> в худшем случае<ref>[http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.109.4875&rep=rep1&type=pdf Ron Wein {{---}} Efficient Implementation of Red-Black Trees.]</ref>.
===Balanced TreesДекартово дерево по неявному ключу===[[Файл:Balanced tree.png |center|Пример ]]
Представим последовательность Также, можем хранить последовательности вершин эйлерова обхода в виде сбалансированного двоичного [[Декартово_дерево_по_неявному_ключу|декартовом дереве по неявному ключу]]. Глубина декартового дерева. Будем использовать красно-черное дерево, построенного на массиве из <tex>n</tex> вершин, будет поддерживаться равной <tex>O(\log n)</tex>.
Объединение Операции объединения и разделение красно-черных деревьев выполняется разделения также выполняются за <tex>O(\log n)</tex>.
Для каждой вершины храним указатели на её первое и последнее вхождение в последовательность. Значит, имеем доступ к ним за <tex>О(1)</tex>==См.также==* [[Link-Cut Tree]]
Запрос о принадлежности вершин к одной компоненте связности выполняется за O(log n) проверкой лежат ли эти вершины в одном дереве.== Примечания ==<references/>
==Источники информации==* [https://en.wikipedia.org/wiki/Euler_tour_technique Wikipedia {{---}} Euler tour technique]* [Файлhttp:Balanced tree1//courses.png |center|Пример csail.mit.edu/6.851/spring07/scribe/lec05.pdf Advanced Data Structures {{---}} Euler tour trees]* [http://codeforces.com/blog/entry/18369?mobile=true&locale=en CodeForces {{---}} On Euler tour trees]* [http://logic.pdmi.ras.ru/csclub/node/2819 Лекториум{{---}} Лекция Павла Маврина об эйлеровых обходах]
==Похожие [[Категория: Алгоритмы и структуры==данных]]Про link-cut trees[[Категория: Обходы графов]][[Категория: Эйлеровы графы]]
1632
правки

Навигация