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

Материал из Викиконспекты
Перейти к: навигация, поиск
(Реализация)
(Реализация)
Строка 44: Строка 44:
 
===Реализация===
 
===Реализация===
  
  '''int[][]''' findMaxFlow('''pair<int, int>''' E, '''double[][]''' C, '''double[][]''' P, '''int''' s, '''int''' t):  
+
  '''double[][]''' findMaxFlow('''pair<int, int>''' E, '''double[][]''' C, '''double[][]''' P, '''int''' s, '''int''' t):  
 
     '''for''' (u, v) '''in''' <tex>E</tex>:
 
     '''for''' (u, v) '''in''' <tex>E</tex>:
 
         flow[u][v] = 0
 
         flow[u][v] = 0

Версия 15:44, 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. Поток минимальной стоимости найден, т.к в остаточной сети не осталось ни одного пути.
  • Конец.

Реализация

double[][] findMaxFlow(pair<int, int> E, double[][] C, double[][] P, int s, int t): 
   for (u, v) in [math]E[/math]:
       flow[u][v] = 0
   while [math]\exists[/math] путь [math]s \leadsto t[/math] в остаточной сети [math]G_f[/math]:
       path = путь [math]s \leadsto t[/math] с наименьшей стоимостью P
       maxFlow = [math]\displaystyle  \min_{(u, v) \in path} C[u][v] - flow[u][v][/math]
       for (u, v) in path:
           flow[u][v] = flow[u][v] + maxFlow
   return flow

Асимптотика

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

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

См. также

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