Изменения

Перейти к: навигация, поиск
Асимптотика
==Жадный Алгоритм=====Идея=алгоритм==Идея заключается в том, чтобы по одному находить пути из [[Определение_сети,_потока|истока]] <tex>s</tex> в [[Определение_сети,_потока|сток]] <tex>t</tex>, пока это возможно. [[Обход в глубину, цвета вершин| Обход в глубину]] найдёт все пути из <tex>s</tex> в <tex>t</tex>, если из <tex>s</tex> достижима <tex>t</tex>, а [[Определение_сети,_потока|пропускная способность]] каждого ребра <tex>c(u, v)>0</tex> поэтому, насыщая рёбра, мы хотя бы единожды достигнем стока <tex>t</tex>, следовательно блокирующий поток всегда найдётся.
===Асимптотика===Используя <tex>dfs</tex> , каждый путь находится за <tex>O(E)</tex>, где <tex>E</tex> — число рёбер в графе. Поскольку каждый путь насыщает как минимум одно ребро, всего будет <tex>O(E)</tex> путей. Итого общая асимптотика составляет <tex>O(E^2)</tex>.
==Удаляющий обход==
Аналогично предыдущей идее, однако будем удалять в процессе обхода в глубину из графа все рёбра, вдоль которых не получится дойти до стока <tex>t</tex>. Это очень легко реализовать: достаточно удалять ребро после того, как мы просмотрели его в обходе в глубину (кроме того случая, когда мы прошли вдоль ребра и нашли путь до стока). С точки зрения реализации, надо просто поддерживать в списке смежности каждой вершины указатель на первое не удалённое ребро, и увеличивать этот указатель в цикле внутри обхода в глубину. Корректность при этом сохраняется согласно предыдущему пункту.
 
'''int''' dfs('''int''' <tex>v</tex>, '''int''' flow)
'''if''' (flow == 0)
'''return''' 0
'''if''' (<tex>v</tex> == <tex>t</tex>)
'''return''' flow
'''for''' (<tex>u</tex> = ptr[<tex>v</tex>] '''to''' n)
'''if''' (<tex>vu \in E</tex>)
pushed = dfs(<tex>u</tex>, min(flow, c(<tex>vu</tex>) - f(<tex>vu</tex>)))
f(<tex>vu</tex>) += pushed
f(<tex>uv</tex>) -= pushed
'''return''' pushed
ptr[<tex>v</tex>]++
'''return''' 0
 
'''main'''()
'''...'''
flow = 0
'''for''' ('''int''' i = 1 '''to''' n)
ptr[i] = 0
'''do'''
pushed = dfs(<tex>s</tex>, <tex>\infty</tex>)
flow += pushed
'''while''' (pushed > 0)
 
 
Если обход в глубину достигает стока, насыщается как минимум одно ребро, иначе как минимум один указатель продвигается вперед. Значит один запуск обхода в глубину работает за <tex>O(V + K)</tex>, где <tex>V</tex> — число вершин в графе, а <tex>K</tex> — число продвижения указателей. Ввиду того, что всего запусков обхода в глубину в рамках поиска одного [[Блокирующий поток|блокирующего потока]] будет <tex>O(P)</tex>, где <tex>P</tex> — число рёбер, насыщенных этим блокирующим потоком, то весь алгоритм поиска блокирующего потока отработает за <tex>O(PV + \sum\limits_i{K_i})</tex>, что, учитывая, что все указатели в сумме прошли расстояние <tex>O(E)</tex>, дает асимптотику <tex>O(PV + E)</tex>. В худшем случае, когда блокирующий поток насыщает все рёбра, асимптотика получается <tex>O(VE)</tex>.
 
<b>Замечание:</b> Если в [[Схема алгоритма Диница|алгоритме Диница]] искать блокирующий поток удаляющим обходом, то его эффективность составит <tex>O(V^2E)</tex>, что уже лучше эффективности [[Алоритм Эдмондса-Карпа|алгоритма Эдмондса-Карпа]] <tex>O(VE^2)</tex>.
 
==Алгоритм Малхотры — Кумара — Махешвари==
===Идея===
По-прежнему по одному находятся пути из Для каждой вершины вводится потенциал потока, равный максимальному дополнительному потоку, который может пройти через эту вершину. Далее запускаем цикл, на каждой итерации которого определяем вершину <tex>v</tex> с минимальным потенциалом <tex>sp</tex> в . Затем пускается поток величины <tex>tp</tex>из истока в сток, проходящий через эту вершину. При этом если [[Дополняющая сеть, дополняющий путь|остаточная пропускная способность]] ребра равна нулю, то это ребро удаляется. Также, но применяется следующая оптимизация: в процессе обхода в глубину удаляются все ребравершины, вдоль у которых нельзя дойти до стокане остаётся ни одного входящего и/или ни одного выходящего ребра. То естьПри удалении вершины все смежные рёбра удаляются. ===Подробное описание===* Для каждой вершины <tex>v</tex> вычислим входящий и исходящий потенциал: <tex>p_{in}=\sum \limits_{u} c(u, v)</tex> и <tex>p_{out}=\sum \limits_{u} c(v, если для текущей u)</tex>. Пусть <tex>p_{in}(s)=\infty</tex> и <tex>p_{out}(t)=\infty</tex>. Определим потенциал или пропускную способность вершины в [[Определение сети, потока|сети]] <tex>p(v)=min(p_{in}(v), p_{out}(v))</tex> выполнено . Таким образом, потенциал вершины определяет максимально возможное количество потока, который может через неё проходить. Ясно, что через вершины с <tex>dfsp(v) = false0</tex>поток проходить не может. Следовательно, нужно их можно удалить из графа эту вершину [[Дополняющая сеть, дополняющий путь|вспомогательной сети]]. Удалим эти вершины и все дуги, им инцидентные ей ребра, обновив должным образом потенциалы вершин, смежных с удалёнными. Если в результате появятся новые вершины с <tex>p(v)=0</tex>, удалим рекурсивно и их. В результате во вспомогательной сети останутся только вершины с <tex>p(v)\ne0</tex>. * После этого приступим к построению [[Блокирующий поток|блокирующего потока]]. С точки зрения реализацииПусть вершина <tex>v</tex> принадлежит <tex>k</tex>-ому слою и <tex>p(v)=min (p(w), надо просто поддерживать w \in L_k)</tex>, где <tex>L_k</tex> — <tex>k</tex>-й слой. Протолкнем <tex>p(v)</tex> единиц потока из вершины <tex>v</tex> в списке смежности каждой смежные с ней вершины указатель на первое неудалённое ребропо исходящим дугам с [[Дополняющая сеть, дополняющий путь | остаточной пропускной способностью]] <tex>c_f \ne 0</tex>. Попутно будем переносить проталкиваемый поток в исходную сеть, а также корректировать потенциалы вершин, отправляющих и увеличивать этот указатель принимающих избыток потока. В результате, весь (в цикле внутри обхода виду минимальности потенциала вершины <tex>v</tex>) проталкиваемый поток соберется в глубинувершинах <tex>(k+1)</tex>-го слоя.
===Асимптотика===Если обход в глубину достигает стока* Повторим процесс отправки потока из вершин <tex>(k+1)</tex>-го слоя, насыщается как минимум одно ребросодержащих избыток потока, иначе как минимум один указатель продвигается вперед. Значит один запуск обхода в глубину работает за смежные им вершины <tex>O(V k+ K2)</tex>-го слоя. И так до тех пор, пока весь поток не соберется в последнем слое, где в котором содержится только сток <tex>Kt</tex> - число продвижения указателей, ибо все остальные вершины, ранее ему принадлежащие, были удалены, поскольку их потенциалы нулевые. УчитываяСледовательно, что всего запусков обхода в глубину в рамках поиска одного [[Блокирующий весь поток|блокирующего потока]] будет величины <tex>Op(Pv)</tex>, отправленный из вершины <tex>v</tex>, где <tex>Pp(v)</tex> - минимальный полностью соберется в <tex>t</tex> — число рёбер.  * На втором этапе вновь, насыщенных этим блокирующим потокомначиная с вершины <tex>v</tex>, то весь алгоритм поиска блокирующего осуществляется подвод потока уже по входящим дугам. В результате на первом шаге недостаток потока отработает за переадресуется к узлам <tex>O(PV + \sum\limits_i{K_i}k-1)</tex>-го слоя, чтозатем <tex>(k-2)</tex>-го. И так до тех пор, учитываяпока весь поток величины <tex>p(v)</tex>, что все указатели отправленный в сумме прошли расстояние вершину <tex>v</tex>, где <tex>Op(Ev)</tex>- минимальный, дает асимптотику не соберется в истоке <tex>O(PV + E)s</tex>. В худшем случаеТаким образом, когда блокирующий поток насыщает все ребра, асимптотика получается и во вспомогательной и в основной сети увеличится на величину <tex>O(VE)p</tex>.
<b>Замечание</b> Если в [[Схема алгоритма Диница|алгоритме Диница]] искать блокирующий поток удаляющим обходом, то его эффективность составит <tex>O(V^2E)</tex>, что уже лучше эффективности алгоритма Эдмондса-Карпа <tex>O(VE^2)</tex>.
==Алгоритм узкого места== MPM algorithm(<tex>s, t</tex>)===Идея=== {Для каждой вершины вводится потенциал потока, равный максимальному дополнительному потоку, который может пройти через эту вершину. Далее следует цикл. На каждой его итерации определяется вершина foreach <tex>r(uv) \in E</tex> с минимальным потенциалом <tex>f(uv) \rholeftarrow 0 </tex>; Вычисляем остаточную сеть <tex>R</tex>; Найдём вспомогательный граф <tex>L</tex>. Затем пускается поток величины для <tex>R</tex>; while (<tex>t \rhoin L</tex>) { while (<tex>t</tex> достижима из истока <tex>s</tex> в сток<tex>L</tex>) { найдём <tex>v</tex> с минимальной пропускной способностью <tex>g</tex>; проталкиваем <tex>g</tex> единиц потока из <tex>v</tex> в <tex>t</tex>; проталкиваем <tex>g</tex> единиц потока из <tex>s</tex> в <tex>v</tex>; изменяем <tex>f</tex>, проходящий через эту вершину. При этом если остаточная пропускная способность ребра равна нулю, то это ребро удаляется. Также, удаляются все вершины, у которых не остаётся ни одного входящего <tex>L</tex> и<tex>R</или ни одного выходящего ребра. При удалении вершины все смежные ребра удаляются.tex>; } вычисляем новый вспомогательный граф <tex>L</tex> из <tex>R</tex>; } }
===Асимптотика===
Если информация о входящих и исходящих дугах будет храниться в виде связных списков, то для того, чтобы пропустить поток, на каждой итерации будет выполнено <tex>O(V K + E_i)</tex> действий, где <tex>K = O(V)</tex> соответствует числу рёбер, для которых остаточная пропускная способность уменьшилась, но осталась положительной, а <tex>E_i</tex> — числу удалённых реберрёбер. Таким образом, для поиска блокирующего потока будет выполнено <tex>\sum\limits_i{O(VK+E_i)} = O(VK^2)</tex> действий. == См. также ==* [[Блокирующий поток]]* [[Схема алгоритма Диница]]
<b>Замечание<==Источники информации==* [http:/b> /e-maxx.ru/algo/dinic MAXimal :: algo :: Алгоритм Малхотры — Кумара — Диница]*[http://www.facweb.iitkgp.ernet.in/~arijit/courses/autumn2006/cs60001/lec-flow-4.pdf The MPM Algorithm]*[http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9C%D0%B0%D0%BB%D1%85%D0%BE%D1%82%D1%80%D1%8B_%E2%80%94_%D0%9A%D1%83%D0%BC%D0%B0%D1%80%D0%B0_%E2%80%94_%D0%9C%D0%B0%D1%85%D0%B5%D1%88%D0%B2%D0%B0%D1%80%D0%B8 Алгоритм Малхотры — Кумара — Махешвари]*[http://eprints.utas.edu.au/160/1/iplFlow.pdf Оригинальная публикация алгоритма Малхотры — Кумара — Махешвари для поиска блокирующего потока использует алгоритм узкого места.]
==Волновой алгоритм==
Используя предпотоки, позволяет найти блокирующий поток за <tex>O(V^2)</tex>. Модификация алгоритма Диница, основанная на этом алгоритме, называется алгоритмом Карзанова.
==Источники==* http://ru.wikipedia.org* http[[Категория://e-maxx.ruАлгоритмы и структуры данных]]* http[[Категория://algolist.manual.ruЗадача о максимальном потоке]]
Анонимный участник

Навигация