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

Материал из Викиконспекты
Перейти к: навигация, поиск
(Асимптотика алгоритма)
(Реализация)
Строка 29: Строка 29:
  
 
==Реализация==
 
==Реализация==
   <tex>bfs()</tex>
+
   bfs()
       <tex>q \leftarrow empty </tex>
+
       <tex>Q \leftarrow \emptyset</tex>
       <tex> q.push(s) </tex>
+
       <tex>Q</tex>.push(<tex>s</tex>)
      <tex>while !q.isEmty()</tex>
+
      while <tex>Q \ne \emptyset</tex>
         <tex>for (v : (flow(u,v) > 0) and (dist[v] = 0))</tex>
+
        <tex>u \leftarrow Q</tex>.pop
 +
         <tex>for (v :</tex> поток из <tex>u</tex> в <tex>v</tex> положителен и <tex>v</tex> не посещена)
 
             <tex>dist[v] \leftarrow dist[u] + 1 </tex>
 
             <tex>dist[v] \leftarrow dist[u] + 1 </tex>
             <tex>q.push(v)</tex>
+
             <tex>Q</tex>.push(<tex>v</tex>)
       <tex>q.pop()</tex>
+
       <tex>Q</tex>.pop()
  
   <tex>makeGl()</tex>
+
   makeGl()
       <tex>dist \leftarrow </tex>0
+
       <tex>dist \leftarrow 0</tex>
       <tex>bfs()</tex>
+
       bfs()
      <tex>if (t</tex> достижима<tex>)</tex>
 
        <tex>return true</tex>
 
      <tex>return false</tex>
 
  
   <tex>algorithmDinica()</tex>
+
   algorithmDinica()
       <tex>flow \leftarrow</tex> 0
+
       <tex>flow \leftarrow 0</tex>
       <tex>while makeGL()</tex>
+
       makeGl()
        <tex> f' \leftarrow findBlockingFlow()</tex>
+
      while (<tex>t</tex> достижима)
         <tex> f \leftarrow f' </tex>
+
        Ищем блокирующий поток
       вывести поток <tex> f </tex>
+
         Меняем поток <tex>f</tex>
 +
        makeGl()
 +
       вывести поток <tex>f</tex>
  
 
== Источники ==
 
== Источники ==

Версия 09:45, 17 января 2012

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

Слоистая сеть с пятью слоямию. s = 0, t = 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 \emptyset[/math]
     [math]Q[/math].push([math]s[/math])
     while [math]Q \ne \emptyset[/math]
        [math]u \leftarrow Q[/math].pop
        [math]for (v :[/math] поток из [math]u[/math] в [math]v[/math] положителен и [math]v[/math] не посещена)
           [math]dist[v] \leftarrow dist[u] + 1 [/math]
           [math]Q[/math].push([math]v[/math])
     [math]Q[/math].pop()
  makeGl()
     [math]dist \leftarrow 0[/math]
     bfs()
  algorithmDinica()
     [math]flow \leftarrow 0[/math]
     makeGl()
     while ([math]t[/math] достижима)
        Ищем блокирующий поток
        Меняем поток [math]f[/math]
        makeGl()
     вывести поток [math]f[/math]

Источники