Схема алгоритма Диница — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Источники)
(Определение слоистой сети)
Строка 1: Строка 1:
 
== Определение слоистой сети ==  
 
== Определение слоистой сети ==  
[[Файл:Слоистая_сеть.png|250px |thumb|cental| Слоистая сеть с пятью слоями с истоком в вершине 0 и стоком в вершине 6]]
+
[[Файл:Слоистая_сеть.png|200px |thumb|cental| Слоистая сеть с пятью слоями с истоком в вершине 0 и стоком в вершине 6]]
#[[Дополняющая сеть, дополняющий путь]]
+
Для начала определим для каждой вершины <tex>v</tex> данной сети <tex>G</tex> длину кратчайшего <tex>s \leadsto v</tex> пути из истока и обозначим ее <tex>d[v]</tex> (для этого можно воспользоваться [[Обход в ширину|обходом в ширину]]).<br/> В слоистую сеть включаем только те ребра <tex>(u,v)</tex> исходной сети, для которых <tex>d[u] + 1 = d[v]</tex>.  
#[[Блокирующий поток]]
+
Полученная сеть ациклична, и любой <tex>s \leadsto t</tex> путь во вспомогательной сети является кратчайшим путём в исходной, из свойств обхода в ширину.
#Вспомогательная (слоистая) сеть.
 
::Для начала определим для каждой вершины <tex>v</tex> данной сети <tex>G</tex> длину кратчайшего <tex>s \leadsto v</tex> пути из истока и обозначим ее <tex>d[v]</tex> (для этого можно воспользоваться [[Обход в ширину|обходом в ширину]]).<br/> В слоистую сеть включаем только те ребра <tex>(u,v)</tex> исходной сети, для которых <tex>d[u] + 1 = d[v]</tex>.  
 
::Полученная сеть ациклична, и любой <tex>s \leadsto t</tex> путь во вспомогательной сети является кратчайшим путём в исходной, из свойств обхода в ширину.
 
 
<br/>В примере ребра, обозначенные пунктиром, не входят в слоистую сеть.
 
<br/>В примере ребра, обозначенные пунктиром, не входят в слоистую сеть.
  

Версия 07:04, 15 января 2012

Определение слоистой сети

Слоистая сеть с пятью слоями с истоком в вершине 0 и стоком в вершине 6

Для начала определим для каждой вершины [math]v[/math] данной сети [math]G[/math] длину кратчайшего [math]s \leadsto v[/math] пути из истока и обозначим ее [math]d[v][/math] (для этого можно воспользоваться обходом в ширину).
В слоистую сеть включаем только те ребра [math](u,v)[/math] исходной сети, для которых [math]d[u] + 1 = d[v][/math]. Полученная сеть ациклична, и любой [math]s \leadsto t[/math] путь во вспомогательной сети является кратчайшим путём в исходной, из свойств обхода в ширину.
В примере ребра, обозначенные пунктиром, не входят в слоистую сеть.

Алгоритм

Пусть дана сеть. Требуется найти в этой сети поток [math]f(u,v)[/math] из [math]s[/math] в [math]t[/math] максимальной величины.

Схема алгоритма

  1. Для каждого ребра [math](u,v)[/math] данной сети [math]G[/math] зададим [math]f(u,v) = 0[/math].
  2. Построим вспомогательную сеть [math]G_L[/math] из дополняющей сети [math]G_f[/math] данного графа [math]G[/math]. Если [math]d[t] = \infty[/math], остановиться и вывести [math]f[/math].
  3. Найдем блокирующий поток [math]f'[/math] в [math]G_L[/math]..
  4. Дополним поток [math]f[/math] найденным потоком [math]f'[/math] и перейдем к шагу 2.

Корректность алгоритма

Покажем, что если алгоритм завершается, то на выходе у него получается поток именно максимальной величины.

В самом деле, предположим, что в какой-то момент во вспомогательной сети, построенной для остаточной сети, не удалось найти блокирующий поток. Это означает, что сток вообще не достижим во вспомогательной сети из истока. Но поскольку она содержит в себе все кратчайшие пути из истока в остаточной сети, это в свою очередь означает, что в остаточной сети нет пути из истока в сток. Следовательно, применяя теорему Форда-Фалкерсона, получаем, что текущий поток в самом деле максимален.

Асимптотика алгоритма

Утверждение:
Расстояние между истоком и стоком строго увеличивается после каждой фазы алгоритма, т.е. [math]d'[t] \gt d[t][/math], где [math]d'[t][/math] — значение, полученное на следующей фазе алгоритма.
[math]\triangleright[/math]
От противного. Рассмотрим кратчайший путь из истока в сток; по предположению, его длина должна сохраниться неизменной. Однако остаточная сеть на следующей фазе содержит только рёбра остаточной сети перед выполнением текущей фазы, либо обратные к ним. Таким образом, пришли к противоречию: нашёлся [math]s \leadsto t[/math] путь, который не содержит насыщенных рёбер и имеет ту же длину, что и кратчайший путь. Этот путь должен был быть «заблокирован» блокирующим потоком, чего не произошло, в чём и заключается противоречие, что и требовалось доказать.
[math]\triangleleft[/math]

Поскольку длина кратчайшего [math]s \leadsto t[/math] пути не может превосходить [math]n - 1[/math], то, следовательно, алгоритм Диница совершает не более [math]n - 1[/math] фазы. Таким образом, в зависимости от того, каким алгоритмом нахождения блокирующего потока мы пользовались, весь алгоритм Диница может выполняться за [math]O(VE^2)[/math] или за [math]O(V^2E)[/math]. Также возможно достичь асимптотики [math]O(VE\log V)[/math], если использовать динамические деревья Слетора и Тарьяна.

Реализация

  bfs()
     [math]q \leftarrow empty [/math]
     [math] q.push(s) [/math]
     while [math]!q.isEmty()[/math]
        for ([math]v[/math] : ([math]flow(u,v) \gt  0[/math]) [math]and[/math] ([math]dist[v] = 0[/math]))
           [math]dist[v] \leftarrow dist[u] + 1 [/math]
           [math]q.push(v)[/math]
     [math]q.pop()[/math]
  makeGl()
     [math]dist \leftarrow [/math]0
     bfs()
     if ([math]t[/math] достижима)
        return true
     return false
  algorithmDinica()
     [math]flow \leftarrow[/math] 0
     while makeGL()
        [math] f' \leftarrow[/math]findBlockingFlow()
        [math] f \leftarrow f' [/math]
     вывести поток [math] f [/math]

Источники