Поиск потока минимальной стоимости методом дополнения вдоль путей минимальной стоимости — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Идея)
(Реализация)
(не показано 48 промежуточных версий 3 участников)
Строка 1: Строка 1:
==Идея==
+
==Теорема Форда-Фалкерсона==
В основе алгоритма лежит [[Теорема Форда-Фалкерсона о потоке минимальной стоимости|теорема Форда-Фалкерсона о потоке минимальной стоимости]]. На каждой итерации алгоритма будем находить путь из  <tex>s</tex> в <tex>t</tex> минимальной стоимости и дополнять поток вдоль этого пути.
+
Задача о потоке минимальной стоимости состоит в нахождении среди всех [[Определение сети, потока|потоков]] данной величины наименее затратного.
У нас появляются ребра отрицательного веса. Выбирать алгоритм для поиска кратчайших путей следует с учетом этого факта.
 
  
==Реализация==
+
{{Лемма
 +
|about=
 +
о представлении потоков
 +
|statement=
 +
Пусть <tex> f </tex> и <tex> g </tex> {{---}} потоки в сети <tex> G </tex>. Тогда <tex> g </tex> можно представить как сумму <tex> f + f'</tex>, где <tex>f'</tex> {{---}} поток в остаточной сети <tex>G_f</tex>.
 +
|proof=  
 +
Рассмотрим произвольное ребро <tex> (u, v) </tex> из <tex> G </tex>. <tex> f'(u, v) = g(u, v) - f(u, v) \leqslant c(u, v) - f(u, v) = c_f(u, v) </tex>. Таким образом, поток через каждое ребро не превосходит пропускной способности остаточной сети.
 +
Антисимметричность и закон сохранения потока проверяются аналогично [[Лемма о сложении потоков|лемме о сложении потоков]].
 +
}}
  
'''for''' <tex>e \in E</tex> {
+
{{Теорема
      <tex>f[e] \leftarrow 0</tex>
+
|statement=
  }
+
Пусть: <tex> G </tex> {{---}} сеть с истоком <tex> s </tex> и стоком <tex> t </tex>, <tex> f </tex> {{---}} поток минимальной стоимости в сети <tex> G </tex> среди потоков величины <tex> a </tex>, <tex> P </tex> {{---}} путь минимальной стоимости <tex> s \leadsto t</tex> в остаточной сети.
'''while''' (существует путь <tex>s \leadsto t</tex> в остаточной сети <tex>G_f</tex>) {
+
Тогда:
      <tex>P \leftarrow</tex> кратчайший в смысле стоимости путь <tex>s \leadsto t</tex>
+
<tex>\forall \delta : 0 \leqslant \delta \leqslant c_f(P)</tex> поток <tex>f + \delta \cdot f_P</tex> {{---}} поток минимальной стоимости среди потоков величины <tex>a + \delta</tex>, где <tex>\delta \cdot f_P</tex> {{---}} поток величины <tex>\delta</tex>, проходящий по пути <tex>P</tex>.
      дополнить поток <tex>f</tex> вдоль <tex>P</tex>
 
}
 
  
==Корректность==
+
|proof=
Непосредственно следует из [[Теорема Форда-Фалкерсона о потоке минимальной стоимости|теоремы Форда-Фалкерсона о потоке минимальной стоимости]].
+
Пусть <tex> g </tex> {{---}} поток минимальной стоимости величины <tex>a + \delta</tex> в <tex>G</tex>. Представим <tex> g = f + f'</tex>, где <tex> f' </tex> {{---}} поток в остаточной сети <tex>G_f</tex>. Тогда разность <tex> g - f</tex> будет потоком в сети <tex>G_f</tex> и по [[Лемма о сложении потоков|лемме о сложении потоков]] его величина будет равна <tex>\delta</tex>.
  
==Асимптотика==
+
По [[Теорема о декомпозиции|теореме о декомпозиции]] <tex> g - f</tex> можно представить как сумму элементарных потоков вдоль путей <tex>P_i : s \leadsto t</tex> и циклов <tex>C_i</tex>. В этом представлении нет отрицательных циклов, иначе прибавление его к <tex> f </tex> даст поток меньшей стоимости. Если есть положительный цикл, то вычтем его из <tex> g </tex> и получим поток меньшей стоимости. Таким образом, <tex>p(C_i) = 0</tex> для всех циклов.
 +
 
 +
Тогда <tex>p(g - f) = \sum\limits_{P_i} p(P_i)\cdot c_f(P_i) \geqslant p(P) \cdot \sum\limits_{P_i}c_f(P_i) \geqslant p(P) \cdot \delta</tex>.
 +
 
 +
Отсюда <tex> p(g) \geqslant p(f) +  p(P) \cdot \delta \geqslant p(g) </tex> и поток <tex>f + \delta \cdot f_P</tex> {{---}} минимальный.
 +
 
 +
}}
 +
 
 +
==Алгоритм==
 +
На основании теоремы построим алгоритм. На каждой итерации алгоритма будем находить путь минимальной стоимости из <tex>s</tex> в <tex>t</tex> в остаточной сети и дополнять поток вдоль него. Выбирать алгоритм для поиска кратчайших путей следует с учетом того, что в ходе алгоритма появляются ребра отрицательного веса.
 +
 
 +
===Описание===
 +
* Начало.
 +
* '''Шаг 1'''. Для каждого ребра зададим поток равный <tex>0</tex>.
 +
* '''Шаг 2'''. Построим остаточную сеть <tex>G_f</tex>.
 +
* '''Шаг 3'''. Если существует путь <tex>s \leadsto t</tex> в остаточной сети <tex>G_f</tex> {{---}} перейдем к '''шагу 4''', иначе к '''шагу 6'''.
 +
* '''Шаг 4'''. Найдем путь <tex>s \leadsto t</tex> c минимальной стоимостью: путь <tex> P</tex>.
 +
* '''Шаг 5'''. Дополним поток <tex>f</tex> вдоль пути <tex>P</tex>.
 +
* '''Шаг 6'''. Поток минимальной стоимости найден, т.к в остаточной сети не осталось ни одного пути.
 +
* Конец.
 +
 
 +
===Реализация===
 +
 
 +
Пусть задана структура <tex>Edge</tex>:
 +
'''struct''' edge:
 +
    '''int''' from       
 +
    '''int''' to             
 +
    '''double''' c      <font color=green>// пропускная способность ребра</font>
 +
    '''double''' flow    <font color=green>// поток через ребро</font>
 +
    '''double''' price  <font color=green>// стоимость перемещения единицы потока через ребро</font>
 +
 
 +
Будем использовать структуру для хранения ребер графа G.
 +
 
 +
'''Edge[]''' findMinCostMaxFlow(<tex>G: (V, E)</tex>, '''int''' s, '''int''' t):
 +
    '''for''' edge '''in''' <tex>E</tex>:
 +
        edge.flow = 0
 +
    '''while''' <tex>\exists</tex> путь <tex>s \leadsto t</tex> в остаточной сети <tex>G_f</tex>:
 +
        P = путь <tex>s \leadsto t</tex> с наименьшей стоимостью.
 +
        maxFlow = <tex>\displaystyle  \min_{edge \in P} edge.c - edge.flow</tex>
 +
        '''for''' edge '''in''' P:
 +
            edge.flow += maxFlow
 +
    '''return''' <tex>E</tex>
 +
 
 +
===Асимптотика===
 
Каждая итерация выполняется за время работы поиска кратчайшего пути, обозначим его <tex>F(V, E)</tex>. В сетях с целочисленной пропускной способностью итераций будет не более <tex>|f|</tex>.  
 
Каждая итерация выполняется за время работы поиска кратчайшего пути, обозначим его <tex>F(V, E)</tex>. В сетях с целочисленной пропускной способностью итераций будет не более <tex>|f|</tex>.  
  
 
Итого получаем время работы <tex>O(F(V, E) \cdot |f|)</tex>.
 
Итого получаем время работы <tex>O(F(V, E) \cdot |f|)</tex>.
  
== Литература ==
+
==См. также==
 +
*[[Поток минимальной стоимости| Поток минимальной стоимости]]
 +
*[[Использование потенциалов Джонсона при поиске потока минимальной стоимости| Использование потенциалов Джонсона при поиске потока минимальной стоимости]]
 +
 
 +
==Источники информации==
 +
*[https://ru.wikipedia.org/wiki/Теорема_Форда_—_Фалкерсона Wikipedia {{---}} Теорема Форда-Фалкерсона]
 
* Ravindra Ahuja, Thomas Magnanti, James Orlin. Network flows (1993)
 
* Ravindra Ahuja, Thomas Magnanti, James Orlin. Network flows (1993)
  
 +
 +
[[Категория:Алгоритмы и структуры данных]]
 
[[Категория: Задача о потоке минимальной стоимости]]
 
[[Категория: Задача о потоке минимальной стоимости]]

Версия 16:28, 24 января 2016

Теорема Форда-Фалкерсона

Задача о потоке минимальной стоимости состоит в нахождении среди всех потоков данной величины наименее затратного.

Лемма (о представлении потоков):
Пусть [math] f [/math] и [math] g [/math] — потоки в сети [math] G [/math]. Тогда [math] g [/math] можно представить как сумму [math] f + f'[/math], где [math]f'[/math] — поток в остаточной сети [math]G_f[/math].
Доказательство:
[math]\triangleright[/math]

Рассмотрим произвольное ребро [math] (u, v) [/math] из [math] G [/math]. [math] f'(u, v) = g(u, v) - f(u, v) \leqslant c(u, v) - f(u, v) = c_f(u, v) [/math]. Таким образом, поток через каждое ребро не превосходит пропускной способности остаточной сети.

Антисимметричность и закон сохранения потока проверяются аналогично лемме о сложении потоков.
[math]\triangleleft[/math]
Теорема:
Пусть: [math] G [/math] — сеть с истоком [math] s [/math] и стоком [math] t [/math], [math] f [/math] — поток минимальной стоимости в сети [math] G [/math] среди потоков величины [math] a [/math], [math] P [/math] — путь минимальной стоимости [math] s \leadsto t[/math] в остаточной сети.

Тогда:

[math]\forall \delta : 0 \leqslant \delta \leqslant c_f(P)[/math] поток [math]f + \delta \cdot f_P[/math] — поток минимальной стоимости среди потоков величины [math]a + \delta[/math], где [math]\delta \cdot f_P[/math] — поток величины [math]\delta[/math], проходящий по пути [math]P[/math].
Доказательство:
[math]\triangleright[/math]

Пусть [math] g [/math] — поток минимальной стоимости величины [math]a + \delta[/math] в [math]G[/math]. Представим [math] g = f + f'[/math], где [math] f' [/math] — поток в остаточной сети [math]G_f[/math]. Тогда разность [math] g - f[/math] будет потоком в сети [math]G_f[/math] и по лемме о сложении потоков его величина будет равна [math]\delta[/math].

По теореме о декомпозиции [math] g - f[/math] можно представить как сумму элементарных потоков вдоль путей [math]P_i : s \leadsto t[/math] и циклов [math]C_i[/math]. В этом представлении нет отрицательных циклов, иначе прибавление его к [math] f [/math] даст поток меньшей стоимости. Если есть положительный цикл, то вычтем его из [math] g [/math] и получим поток меньшей стоимости. Таким образом, [math]p(C_i) = 0[/math] для всех циклов.

Тогда [math]p(g - f) = \sum\limits_{P_i} p(P_i)\cdot c_f(P_i) \geqslant p(P) \cdot \sum\limits_{P_i}c_f(P_i) \geqslant p(P) \cdot \delta[/math].

Отсюда [math] p(g) \geqslant p(f) + p(P) \cdot \delta \geqslant p(g) [/math] и поток [math]f + \delta \cdot f_P[/math] — минимальный.
[math]\triangleleft[/math]

Алгоритм

На основании теоремы построим алгоритм. На каждой итерации алгоритма будем находить путь минимальной стоимости из [math]s[/math] в [math]t[/math] в остаточной сети и дополнять поток вдоль него. Выбирать алгоритм для поиска кратчайших путей следует с учетом того, что в ходе алгоритма появляются ребра отрицательного веса.

Описание

  • Начало.
  • Шаг 1. Для каждого ребра зададим поток равный [math]0[/math].
  • Шаг 2. Построим остаточную сеть [math]G_f[/math].
  • Шаг 3. Если существует путь [math]s \leadsto t[/math] в остаточной сети [math]G_f[/math] — перейдем к шагу 4, иначе к шагу 6.
  • Шаг 4. Найдем путь [math]s \leadsto t[/math] c минимальной стоимостью: путь [math] P[/math].
  • Шаг 5. Дополним поток [math]f[/math] вдоль пути [math]P[/math].
  • Шаг 6. Поток минимальной стоимости найден, т.к в остаточной сети не осталось ни одного пути.
  • Конец.

Реализация

Пусть задана структура [math]Edge[/math]:

struct edge:
   int from         
   int to               
   double c       // пропускная способность ребра
   double flow    // поток через ребро
   double price   // стоимость перемещения единицы потока через ребро

Будем использовать структуру для хранения ребер графа G.

Edge[] findMinCostMaxFlow([math]G: (V, E)[/math], int s, int t): 
   for edge in [math]E[/math]:
       edge.flow = 0
   while [math]\exists[/math] путь [math]s \leadsto t[/math] в остаточной сети [math]G_f[/math]:
       P = путь [math]s \leadsto t[/math] с наименьшей стоимостью.
       maxFlow = [math]\displaystyle  \min_{edge \in P} edge.c - edge.flow[/math]
       for edge in P:
           edge.flow += maxFlow
   return [math]E[/math]

Асимптотика

Каждая итерация выполняется за время работы поиска кратчайшего пути, обозначим его [math]F(V, E)[/math]. В сетях с целочисленной пропускной способностью итераций будет не более [math]|f|[/math].

Итого получаем время работы [math]O(F(V, E) \cdot |f|)[/math].

См. также

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