Алгоритм поиска блокирующего потока в ациклической сети — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Асимптотика)
Строка 1: Строка 1:
 +
{| class="wikitable" align="center" style="color: red; background-color: black; font-size: 56px; width: 800px;"
 +
|+
 +
|-align="center"
 +
|'''НЕТ ВОЙНЕ'''
 +
|-style="font-size: 16px;"
 +
|
 +
24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян.
 +
 +
Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием.
 +
 +
Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей.
 +
 +
Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить.
 +
 +
''Антивоенный комитет России''
 +
|-style="font-size: 16px;"
 +
|Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению.
 +
|-style="font-size: 16px;"
 +
|[https://meduza.io/ meduza.io], [https://www.youtube.com/c/popularpolitics/videos Популярная политика], [https://novayagazeta.ru/ Новая газета], [https://zona.media/ zona.media], [https://www.youtube.com/c/MackNack/videos Майкл Наки].
 +
|}
 +
 
==Жадный алгоритм==
 
==Жадный алгоритм==
 
Идея заключается в том, чтобы по одному находить пути из [[Определение_сети,_потока|истока]] <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>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>, следовательно блокирующий поток всегда найдётся.
Строка 36: Строка 57:
 
<b>Замечание:</b> Если в [[Схема алгоритма Диница|алгоритме Диница]] искать блокирующий поток удаляющим обходом, то его эффективность составит <tex>O(V^2E)</tex>, что уже лучше эффективности [[Алоритм Эдмондса-Карпа|алгоритма Эдмондса-Карпа]] <tex>O(VE^2)</tex>.
 
<b>Замечание:</b> Если в [[Схема алгоритма Диница|алгоритме Диница]] искать блокирующий поток удаляющим обходом, то его эффективность составит <tex>O(V^2E)</tex>, что уже лучше эффективности [[Алоритм Эдмондса-Карпа|алгоритма Эдмондса-Карпа]] <tex>O(VE^2)</tex>.
  
==Алгоритм Малхотры — Кумара — Махешвари==
+
==Алгоритм Малхотры — Кумара — Махешвари==
 
===Идея===
 
===Идея===
 
Для каждой вершины  вводится потенциал потока, равный максимальному дополнительному потоку, который может пройти через эту вершину. Далее запускаем цикл, на каждой итерации которого определяем вершину <tex>v</tex> с минимальным потенциалом <tex>p</tex>. Затем пускается поток величины <tex>p</tex> из истока в сток, проходящий через эту вершину. При этом если [[Дополняющая сеть, дополняющий путь|остаточная пропускная способность]] ребра равна нулю, то это ребро удаляется. Также, удаляются все вершины, у которых не остаётся ни одного входящего и/или ни одного выходящего ребра. При удалении вершины все смежные рёбра удаляются.
 
Для каждой вершины  вводится потенциал потока, равный максимальному дополнительному потоку, который может пройти через эту вершину. Далее запускаем цикл, на каждой итерации которого определяем вершину <tex>v</tex> с минимальным потенциалом <tex>p</tex>. Затем пускается поток величины <tex>p</tex> из истока в сток, проходящий через эту вершину. При этом если [[Дополняющая сеть, дополняющий путь|остаточная пропускная способность]] ребра равна нулю, то это ребро удаляется. Также, удаляются все вершины, у которых не остаётся ни одного входящего и/или ни одного выходящего ребра. При удалении вершины все смежные рёбра удаляются.
Строка 70: Строка 91:
  
 
===Асимптотика===
 
===Асимптотика===
Если информация о входящих и исходящих дугах будет храниться в виде связных списков, то для того, чтобы пропустить поток, на каждой итерации будет выполнено <tex>O(K + E_i)</tex> действий, где <tex>K = O(V)</tex> соответствует числу рёбер, для которых остаточная пропускная способность уменьшилась, но осталась положительной, а <tex>E_i</tex> — числу удалённых рёбер. Таким образом, для поиска блокирующего потока будет выполнено <tex>\sum\limits_i{O(K+E_i)} = O(K^2)</tex> действий.
+
Если информация о входящих и исходящих дугах будет храниться в виде связных списков, то для того, чтобы пропустить поток, на каждой итерации будет выполнено <tex>O(K + E_i)</tex> действий, где <tex>K = O(V)</tex> соответствует числу рёбер, для которых остаточная пропускная способность уменьшилась, но осталась положительной, а <tex>E_i</tex> числу удалённых рёбер. Таким образом, для поиска блокирующего потока будет выполнено <tex>\sum\limits_i{O(K+E_i)} = O(K^2)</tex> действий.
  
 
== См. также ==
 
== См. также ==

Версия 09:15, 1 сентября 2022

НЕТ ВОЙНЕ

24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян.

Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием.

Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей.

Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить.

Антивоенный комитет России

Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению.
meduza.io, Популярная политика, Новая газета, zona.media, Майкл Наки.

Жадный алгоритм

Идея заключается в том, чтобы по одному находить пути из истока [math]s[/math] в сток [math]t[/math], пока это возможно. Обход в глубину найдёт все пути из [math]s[/math] в [math]t[/math], если из [math]s[/math] достижима [math]t[/math], а пропускная способность каждого ребра [math]c(u, v)\gt 0[/math] поэтому, насыщая рёбра, мы хотя бы единожды достигнем стока [math]t[/math], следовательно блокирующий поток всегда найдётся.

Используя [math]dfs[/math], каждый путь находится за [math]O(E)[/math], где [math]E[/math] — число рёбер в графе. Поскольку каждый путь насыщает как минимум одно ребро, всего будет [math]O(E)[/math] путей. Итого общая асимптотика составляет [math]O(E^2)[/math].

Удаляющий обход

Аналогично предыдущей идее, однако будем удалять в процессе обхода в глубину из графа все рёбра, вдоль которых не получится дойти до стока [math]t[/math]. Это очень легко реализовать: достаточно удалять ребро после того, как мы просмотрели его в обходе в глубину (кроме того случая, когда мы прошли вдоль ребра и нашли путь до стока). С точки зрения реализации, надо просто поддерживать в списке смежности каждой вершины указатель на первое не удалённое ребро, и увеличивать этот указатель в цикле внутри обхода в глубину. Корректность при этом сохраняется согласно предыдущему пункту.

 int dfs(int [math]v[/math], int flow) 
   if (flow == 0) 
     return 0
   if ([math]v[/math] == [math]t[/math])
     return flow
   for ([math]u[/math] = ptr[[math]v[/math]] to n)
     if ([math]vu \in E[/math])
       pushed = dfs([math]u[/math], min(flow, c([math]vu[/math]) - f([math]vu[/math])))
       f([math]vu[/math]) += pushed
       f([math]uv[/math]) -= pushed
       return pushed
     ptr[[math]v[/math]]++
   return 0
 main()
   ...
   flow = 0
   for (int i = 1 to n)
     ptr[i] = 0
   do
     pushed = dfs([math]s[/math], [math]\infty[/math])
     flow += pushed
   while (pushed > 0)


Если обход в глубину достигает стока, насыщается как минимум одно ребро, иначе как минимум один указатель продвигается вперед. Значит один запуск обхода в глубину работает за [math]O(V + K)[/math], где [math]V[/math] — число вершин в графе, а [math]K[/math] — число продвижения указателей. Ввиду того, что всего запусков обхода в глубину в рамках поиска одного блокирующего потока будет [math]O(P)[/math], где [math]P[/math] — число рёбер, насыщенных этим блокирующим потоком, то весь алгоритм поиска блокирующего потока отработает за [math]O(PV + \sum\limits_i{K_i})[/math], что, учитывая, что все указатели в сумме прошли расстояние [math]O(E)[/math], дает асимптотику [math]O(PV + E)[/math]. В худшем случае, когда блокирующий поток насыщает все рёбра, асимптотика получается [math]O(VE)[/math].

Замечание: Если в алгоритме Диница искать блокирующий поток удаляющим обходом, то его эффективность составит [math]O(V^2E)[/math], что уже лучше эффективности алгоритма Эдмондса-Карпа [math]O(VE^2)[/math].

Алгоритм Малхотры — Кумара — Махешвари

Идея

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

Подробное описание

  • Для каждой вершины [math]v[/math] вычислим входящий и исходящий потенциал: [math]p_{in}=\sum \limits_{u} c(u, v)[/math] и [math]p_{out}=\sum \limits_{u} c(v, u)[/math]. Пусть [math]p_{in}(s)=\infty[/math] и [math]p_{out}(t)=\infty[/math]. Определим потенциал или пропускную способность вершины в сети [math]p(v)=min(p_{in}(v), p_{out}(v))[/math]. Таким образом, потенциал вершины определяет максимально возможное количество потока, который может через неё проходить. Ясно, что через вершины с [math]p(v)=0[/math] поток проходить не может. Следовательно, их можно удалить из вспомогательной сети. Удалим эти вершины и дуги, им инцидентные, обновив должным образом потенциалы вершин, смежных с удалёнными. Если в результате появятся новые вершины с [math]p(v)=0[/math], удалим рекурсивно и их. В результате во вспомогательной сети останутся только вершины с [math]p(v)\ne0[/math].
  • После этого приступим к построению блокирующего потока. Пусть вершина [math]v[/math] принадлежит [math]k[/math]-ому слою и [math]p(v)=min (p(w), w \in L_k)[/math], где [math]L_k[/math][math]k[/math]-й слой. Протолкнем [math]p(v)[/math] единиц потока из вершины [math]v[/math] в смежные с ней вершины по исходящим дугам с остаточной пропускной способностью [math]c_f \ne 0[/math]. Попутно будем переносить проталкиваемый поток в исходную сеть, а также корректировать потенциалы вершин, отправляющих и принимающих избыток потока. В результате, весь (в виду минимальности потенциала вершины [math]v[/math]) проталкиваемый поток соберется в вершинах [math](k+1)[/math]-го слоя.
  • Повторим процесс отправки потока из вершин [math](k+1)[/math]-го слоя, содержащих избыток потока, в смежные им вершины [math](k+2)[/math]-го слоя. И так до тех пор, пока весь поток не соберется в последнем слое, в котором содержится только сток [math]t[/math], ибо все остальные вершины, ранее ему принадлежащие, были удалены, поскольку их потенциалы нулевые. Следовательно, весь поток величины [math]p(v)[/math], отправленный из вершины [math]v[/math], где [math]p(v)[/math] - минимальный полностью соберется в [math]t[/math].
  • На втором этапе вновь, начиная с вершины [math]v[/math], осуществляется подвод потока уже по входящим дугам. В результате на первом шаге недостаток потока переадресуется к узлам [math](k-1)[/math]-го слоя, затем [math](k-2)[/math]-го. И так до тех пор, пока весь поток величины [math]p(v)[/math], отправленный в вершину [math]v[/math], где [math]p(v)[/math] - минимальный, не соберется в истоке [math]s[/math]. Таким образом, поток и во вспомогательной и в основной сети увеличится на величину [math]p[/math].


MPM algorithm([math]s, t[/math])
{
   foreach [math](uv) \in E[/math]
     [math]f(uv) \leftarrow 0 [/math];
   Вычисляем остаточную сеть [math]R[/math];
   Найдём вспомогательный граф [math]L[/math] для [math]R[/math];
   while ([math]t \in L[/math])
   {
     while ([math]t[/math] достижима из [math]s[/math] в [math]L[/math])
     {
       найдём [math]v[/math] с минимальной пропускной способностью [math]g[/math];
       проталкиваем [math]g[/math] единиц потока из [math]v[/math] в [math]t[/math];
       проталкиваем [math]g[/math] единиц потока из [math]s[/math] в [math]v[/math];
       изменяем [math]f[/math], [math]L[/math] и [math]R[/math];
     }
     вычисляем новый вспомогательный граф [math]L[/math] из [math]R[/math];
   }
}

Асимптотика

Если информация о входящих и исходящих дугах будет храниться в виде связных списков, то для того, чтобы пропустить поток, на каждой итерации будет выполнено [math]O(K + E_i)[/math] действий, где [math]K = O(V)[/math] соответствует числу рёбер, для которых остаточная пропускная способность уменьшилась, но осталась положительной, а [math]E_i[/math] — числу удалённых рёбер. Таким образом, для поиска блокирующего потока будет выполнено [math]\sum\limits_i{O(K+E_i)} = O(K^2)[/math] действий.

См. также

Источники информации