Изменения

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

Динамика по поддеревьям

5775 байт добавлено, 19:10, 4 сентября 2022
м
rollbackEdits.php mass rollback
== Задача о паросочетании максимального веса в дереве ==
Пусть задано взвешенное дерево, с весами, обозначенными как <tex>w_{i,j}</tex>, где <tex>i</tex> и <tex>j</tex> — вершины дерева, соединённые ребром. Задача: составить такое [[Теорема_о_максимальном_паросочетании_и_дополняющих_цепях | паросочетание]], чтобы суммарный вес всех рёбер, входящих в него, был максимальным.
{{Задача
|definition = Пусть задано взвешенное дерево, с весами, обозначенными как <tex>w_{i,j}</tex>, где <tex>i</tex> и <tex>j</tex> — вершины дерева, соединённые ребром.. Необходимо составить такое [[Теорема_о_максимальном_паросочетании_и_дополняющих_цепях | паросочетание]], чтобы суммарный вес всех рёбер, входящих в него, был максимальным.
}}
Для решения данной задачи существует несколько алгоритмов. Например, [[алгоритм_Куна_для_поиска_максимального_паросочетания | алгоритм Куна]], который имеет верхнюю оценку порядка <tex>O \left ( n^3 \right )</tex>. Но так как нам дано дерево, то можно использовать динамическое программирование, время работы алгоритма с которым улучшается до <tex>O \left ( n \right )</tex>.
Теперь оценим количество операций, необходимых нам для нахождения <tex>c[root]</tex>. Так как <tex>c[i]=\max \left ( a[i],b[i] \right )</tex>, то для вычисления <tex>c[root]</tex> необходимо вычислить <tex>a[root]</tex>, <tex>b[root]</tex>. Для вычисления и того, и другого необходимо время порядка <tex>O \left ( \sum_{x=1}^n \limits \left | Ch(x) \right | \right )=O \left ( n \right )</tex>, где <tex> n </tex> количество число вершин в дереве. 
=== Псевдокод ===
<font color = darkgreen>// в основной процедуре вызываем dfs от корня(root), после этого ответ будет хранится в c[root] </font color = darkgreen>
'''function''' dfs(x: '''int''', a: '''int[]''', b: '''int[]''', c: '''int[]''', w: '''int[][]''', Ch: '''int[]'''):
'''for''' (i : Ch[x])
dfs(i, a, b, c, w, Ch)
a[x] = max(a[x], b[i] + w[x][i] - с[i]) <font color = darkgreen>// по формуле выше, но без b[x] (прибавим его один раз в конце) </font color = darkgreen>
b[x] += с[i]
a[x] += b[x] <font color = darkgreen>// так как в a[x] пока что хранится только на сколько мы можем увеличить ответ если будем использовать вершину x</font color = darkgreen>
c[x] = max(a[x], b[x])
'''function''' dfs== Задача о сумме длин всех путей в дереве =={{Задача|definition = Найти сумму длин всех путей в дереве.}}Решим эту задачу за <tex> O(n) </tex>. Пусть задано подвешенное дерево. Рассмотрим пути проходящие в поддереве вершины <tex> v </tex>. Во-первых, это пути, не проходящие через эту вершину, то есть все пути в поддеревьях её сыновей. Во-вторых, пути, которые оканчиваются вершиной <tex> v </tex>. И в-третьих, это пути, проходящие через вершину <tex> v </tex>, они начинаются из поддерева одного из сыновей этой вершины и заканчиваются в другом поддереве одного из сыновей вершины <tex> v </tex>. Теперь подсчитаем пути для каждого варианта. Обозначим <tex> S[v]\ - </tex> размер поддерева <tex> v </tex>, <tex> F[v]\ - </tex> сумма длин всех путей в поддереве вершины <tex> v </tex>, <tex> G[v]\ - </tex> сумма длин всех путей начинающихся в поддереве вершины v и оканчивающихся вершиной <tex> v </tex>, <tex> H[v]\ - </tex> сумма длин всех путей проходящих через вершину <tex> v </tex>. Если вершина <tex> u </tex> лист, то <tex> S[u] </tex> = 1, а <tex> G[u] </tex> = <tex> H[u] </tex> = 0.# Пути не проходящие через эту вершину. Это просто сумма суммы длин путей для всех поддеревьев детей или <tex> \sum_{x: '''int'''\in Ch(v):} \limits F[x]</tex>. '''for''' (child # Пути оканчивающиеся в вершине <tex> v </tex>. Рассмотрим ребро, соединяющее вершину <tex> v </tex> и одного ее сына, пусть это будет вершина <tex> g </tex>. Переберем все пути, которые начинаются с этого ребра и идут вниз. Сумма длин всех таких путей будет сумма путей оканчивающихся в <tex> g + S[g] </tex>, так как суммарная длина путей оканчивающихся в вершине <tex> g </tex> уже сосчитана и каждый такой путь, которых ровно <tex> S[g] </tex> мы продлили ребром, соединяющим вершины <tex> v </tex> и <tex> g </tex>. Суммарная длина таких путей: <tex> G[v] = \sum_{x \in Ch(v)} \limits {\Bigl(G[x]+ S[x]\Bigl)}</tex>. dfs(child) a# Пути проходящие через вершину <tex> v </tex>. Рассмотрим двух сыновей этой вершины: <tex> x </tex> и <tex> y </tex>. Нам надо подсчитать все пути, которые поднимаются из поддерева <tex> x </tex> в <tex> v </tex> и затем опускаются в поддерево <tex> y </tex> и наоборот. То есть по каждому пути, оканчивающимся в вершине <tex> x </tex> мы пройдем столько раз сколько элементов в поддереве <tex> y </tex>, следовательно суммарная длина таких путей будет <tex> G[x] = max(aS[y] </tex>. Аналогично, если будем подниматься из поддерева <tex> y </tex>. Также надо учитывать сколько раз мы проходим по ребрам, соединяющим вершины <tex> x </tex> <tex> v </tex> и <tex> y </tex> <tex> x </tex>. Итого для двух вершин <tex> x </tex> и <tex> y </tex>: <tex> G[x], bS[childy] + wG[y]S[x]+ 2S[childx] - сS[childy]) <font color = darkgreen/tex>//по формуле выше, но без b[следовательно ( <tex> x],y \in Ch(прибавим его один раз в концеv) </font color tex>) <tex> H[v] = darkgreen> b\sum_{x,y\ x \ne y} \limits{\Bigl(G[x]S[y] += сG[childy] aS[x] += b2S[x] S[y]\Bigl)} </tex>. Но такой подсчет испортит асимптотику до <font color = darkgreentex>O(n^2) <// так как в atex>. Заметим, что <tex> \sum_{x,y} \limits {\Bigl(G[x]S[y]\Bigl)} = \sum_{x} \limits {G[x] пока } \sum_{y} \limits {S[y]} </tex>. Но еще надо учесть, что хранится только на сколько мы можем увеличить ответ если будем использовать вершину <tex> x\ne y </font color tex>, следовательно <tex> \sum_{x,y\ x \ne y} \limits{\Bigl(G[x]S[y]\Bigl)} = darkgreen\sum_{x} \limits {G[x]} \sum_{y} \limits {S[y]} - \sum_{x} \limits {\Bigl(G[x]S[x]\Bigl)} </tex>. Аналогично для <tex> cS[x]S[y] </tex>. Итак: <tex> H[v] = max\biggl(\sum_{x} \limits {G[x]} \sum_{y} \limits {S[y]} - \sum_{x} \limits {\Bigl(G[x]S[x]\Bigl)} \biggl) + \biggl(\sum_{x} \limits {S[x]} \sum_{y} \limits {S[y]} - \sum_{x} \limits {\Bigl(aS[x], bS[x]\Bigl)} \biggl)</tex>. Ответ задачи: <font color tex> F[v] = darkgreen\sum_{x \in Ch(v)} \limits F[x] + G[v] + H[v] </tex>. Асимптотика каждого слагаемого равна <tex>O \left ( \sum_{x=1}^n \limits \left | Ch(x) \right | \right )=O \left ( n \right )</tex>, где <tex> n </tex> — число вершин в основной процедуре вызываем dfs от корнядереве, следовательно и время работы самого алгоритма <tex> O \left (rootn \right ), после этого ответ будет хранится в c[root] </font color = darkgreentex>.
== Амортизированные оценки для ДП на дереве ==
}}
==См. Такжетакже==
* [[Задача коммивояжера, ДП по подмножествам]]
* [[Задача о числе путей в ациклическом графе]]
[[Категория: Дискретная математика и алгоритмы]]
[[Категория: Динамическое программирование]]
[[Категория: Другие задачи динамического программирования]]
[[Категория:Алгоритмы на графах]]
1632
правки

Навигация