Link-Cut Tree — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Решение задачи в частном случае)
(Решение задачи в частном случае)
Строка 6: Строка 6:
  
 
==Решение задачи в частном случае==
 
==Решение задачи в частном случае==
Сначала научимся выполнять эти операции для частного случая, в котором все деревья - это пути. Для этого представим путь в виде splay-дерева, в которм ключи выбираются равными глубине вершины.
+
Сначала научимся выполнять эти операции для частного случая, в котором все деревья - это пути. Для этого представим путь в виде splay-дерева, в которм ключи выбираются равными глубине вершины. [[Файл:Path_to_tree.png|250px|thumb|right|Пример построения дерева для пути]]
[[Файл:Path_to_tree.png|250px|thumb|right|Пример построения дерева для пути]]
 
 
Тогда операциям link и cut будут соответсвовать merge и split.
 
Тогда операциям link и cut будут соответсвовать merge и split.
  
Строка 14: Строка 13:
 
сумма
 
сумма
  
Чтобы прибавить <tex>\alpha</tex> на пути от вершины <tex>v</tex> до корня, надо вызвать <tex>splay(v)</tex>, прибавить <tex>\alpha</tex> к <tex>\Delta w(v)</tex> и вычесть <tex>\alpha</tex> от <tex>\Delta w(v.right)</tex>, чтобы сохранить веса вершин которые находятся ниже <tex>v</tex> в пути.
+
При прибавлении <tex>\alpha</tex> на пути от вершины <tex>v</tex> до корня, сначала вызвается <tex>splay(v)</tex>, после чего в левом поддереве находятся вершины, которые лежат на пути к корню. Затем надо прибавить <tex>\alpha</tex> к <tex>\Delta w(v)</tex> и ,чтобы сохранить веса вершин, которые находятся ниже в пути, вычесть <tex>\alpha</tex> от <tex>\Delta w(v.right)</tex>.
[[Файл:Linkcut_weights.png|250px|thumb|right|Представление веса вершины]]
+
[[Файл:Linkcut_weights.png|250px|thumb|right|]]
  
 
Для поиска минимума поступим аналогично. Определим <tex>\Delta min(v)</tex> таким образом, чтобы сохранялся следующий инвариант: <tex>min(v) = \Delta min(v) + w(v) </tex>. Пусть <tex>l</tex> и <tex>r</tex> дети <tex>v</tex>, тогда
 
Для поиска минимума поступим аналогично. Определим <tex>\Delta min(v)</tex> таким образом, чтобы сохранялся следующий инвариант: <tex>min(v) = \Delta min(v) + w(v) </tex>. Пусть <tex>l</tex> и <tex>r</tex> дети <tex>v</tex>, тогда
Строка 27: Строка 26:
  
 
Чтобы найти минимум на пути, надо вызвать <tex>splay(v)</tex>, а затем сравнить минимум <tex>v</tex> и минимум её левого ребенка.
 
Чтобы найти минимум на пути, надо вызвать <tex>splay(v)</tex>, а затем сравнить минимум <tex>v</tex> и минимум её левого ребенка.
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
==Link-cut tree==
 +
Чтобы обобщить, разобъем дерево на множество непересекающихся путей. Каждое ребро обозначим либо solid-ребром, либо dashed-ребром. Все пути в представляемом дереве хранятся в виде splay-деревьев. Корень каждого splay-дерева хранит указатель на вершину-родителя.
 +
[[Файл:Linkcut_paths.png|500px||center|Разбиение дерева на пути]]
 +
 +
Ключевая операция в link-cut-деревьях {{---}} <tex>expose(u)</tex>. После её выполнения <tex>u</tex> лежит на одном пути с корнем представляемого дерева и при этом становится корнем в splay-дереве получившегося пути.
 +
[[Файл:Linkcut_expose.png|500px||center|Разбиение дерева на пути]]

Версия 23:34, 8 июня 2014

Link-cut tree — это структура данных, которая хранит лес деревьев и позволяет выполнять следующие операции:

  • искать минимум на пути от вершины до корня;
  • прибавлять константу на пути от вершины до корня;
  • link(u,w) -- подвешивать одно дерево на другое;
  • cut(v) -- отрезать дерево с корнем в вершине v.

Решение задачи в частном случае

Сначала научимся выполнять эти операции для частного случая, в котором все деревья - это пути. Для этого представим путь в виде splay-дерева, в которм ключи выбираются равными глубине вершины.
Пример построения дерева для пути

Тогда операциям link и cut будут соответсвовать merge и split.

Чтобы прибавлять заданное число на пути от вершины до корня, будем в каждой вершине хранить велечину [math]\Delta w[/math], которая равна разнице между весом вершины и весом её ролителя. Для корня это значение равно весу самого корня. Поэтому вес вершины определятся следующим образом:

сумма

При прибавлении [math]\alpha[/math] на пути от вершины [math]v[/math] до корня, сначала вызвается [math]splay(v)[/math], после чего в левом поддереве находятся вершины, которые лежат на пути к корню. Затем надо прибавить [math]\alpha[/math] к [math]\Delta w(v)[/math] и ,чтобы сохранить веса вершин, которые находятся ниже в пути, вычесть [math]\alpha[/math] от [math]\Delta w(v.right)[/math].

Linkcut weights.png

Для поиска минимума поступим аналогично. Определим [math]\Delta min(v)[/math] таким образом, чтобы сохранялся следующий инвариант: [math]min(v) = \Delta min(v) + w(v) [/math]. Пусть [math]l[/math] и [math]r[/math] дети [math]v[/math], тогда

[math]min(v) = min\{w(v), min(l), min(r)\}[/math]

[math]\Delta min(v) = min(v) - w(v) \\ = min\{w(v) - w(v), min(l) - w(v), min(r) - w(v)\} \\ = min\{0, (\Delta min(l) + w(l)) - w(v), (\Delta min(r) + w(r)) - w(v)\} \\ = min\{0, \Delta min(l) + \Delta w(l), \Delta min(r) + \Delta w(r)\}[/math]

Чтобы найти минимум на пути, надо вызвать [math]splay(v)[/math], а затем сравнить минимум [math]v[/math] и минимум её левого ребенка.





Link-cut tree

Чтобы обобщить, разобъем дерево на множество непересекающихся путей. Каждое ребро обозначим либо solid-ребром, либо dashed-ребром. Все пути в представляемом дереве хранятся в виде splay-деревьев. Корень каждого splay-дерева хранит указатель на вершину-родителя.

Разбиение дерева на пути

Ключевая операция в link-cut-деревьях — [math]expose(u)[/math]. После её выполнения [math]u[/math] лежит на одном пути с корнем представляемого дерева и при этом становится корнем в splay-дереве получившегося пути.

Разбиение дерева на пути