Алгоритм отмены цикла минимального среднего веса — различия между версиями
 (→Псевдокод) (Метки: правка с мобильного устройства, правка из мобильной версии)  | 
				м (rollbackEdits.php mass rollback)  | 
				||
| (не показано 65 промежуточных версий 4 участников) | |||
| Строка 12: | Строка 12: | ||
Более формально:  | Более формально:  | ||
| − | * '''Шаг 1'''. Рассмотрим некоторый поток <tex>f</tex>.    | + | * '''Шаг <tex>1</tex>'''. Рассмотрим некоторый поток <tex>f</tex>.    | 
| − | * '''Шаг 2'''. Найдем цикл <tex>C</tex>, обладающий наименьшим средним весом. Если <tex>\mu (C) \geqslant 0</tex>, то <tex>f</tex> {{---}} поток минимальной стоимости и алгоритм завершается.  | + | * '''Шаг <tex>2</tex>'''. Найдем цикл <tex>C</tex>, обладающий наименьшим средним весом. Если <tex>\mu (C) \geqslant 0</tex>, то <tex>f</tex> {{---}} поток минимальной стоимости и алгоритм завершается.  | 
| − | * '''Шаг 3'''. Отменим цикл <tex>C</tex>, пустив по нему максимально возможный поток: <tex>f = f + c_{f}(C)\cdot f_{C}</tex>. Перейдем к '''шагу 1'''.  | + | * '''Шаг <tex>3</tex>'''. Отменим цикл <tex>C</tex>, пустив по нему максимально возможный поток: <tex>f = f + c_{f}(C)\cdot f_{C}</tex>. Перейдем к '''шагу <tex>1</tex>'''.  | 
===Сложность===  | ===Сложность===  | ||
Для сетей с целочисленными стоимостями на ребрах <tex>O(VE\cdot VE\log{CV})</tex>, с вещественными {{---}} <tex>O(VE\cdot VE^{2}\log{V})</tex>.  | Для сетей с целочисленными стоимостями на ребрах <tex>O(VE\cdot VE\log{CV})</tex>, с вещественными {{---}} <tex>O(VE\cdot VE^{2}\log{V})</tex>.  | ||
В обоих случаях <tex>O(VE)</tex> времени тратится на поиск цикла минимального среднего веса.  | В обоих случаях <tex>O(VE)</tex> времени тратится на поиск цикла минимального среднего веса.  | ||
| + | |||
| + | ===Псевдокод===  | ||
| + |   '''Edge[]''' findMin('''Graph''' G)  | ||
| + |       '''while''' f  | ||
| + |           <font color="green">// найдём M(C) {{---}} вес минимального цикла</font>  | ||
| + |           C = c : M(c) = <tex>\min\limits_c</tex> M(c)    | ||
| + |           '''if''' M(C) <tex>\geqslant</tex> 0  | ||
| + |               <font color="green">// Если величина M(C) положительна, то мы нашли f {{---}} поток минимальной стоимости, на этом алгоритм завершается</font>  | ||
| + |               '''return''' f                               | ||
| + |           '''else'''  | ||
| + |               <font color="green">// в противном случае отменяем цикл</font>  | ||
| + |               f += c_f * f(C)  | ||
===Корректность===  | ===Корректность===  | ||
| − | Пусть <tex>f</tex> {{---}} поток минимальной стоимости.   | + | Пусть <tex>f</tex> {{---}} поток минимальной стоимости. Введём на нашей сети функцию [[Алгоритм Джонсона|потенциалов]] <tex>\varphi</tex>.  | 
{{Определение  | {{Определение  | ||
| − | |definition='''  | + | |definition='''Приведённой стоимостью''' (англ. ''reduced cost'') ребра назовем следующую величину: <tex>p_{\varphi}(uv)=\varphi(u) + p(uv) - \varphi(v)</tex>.}}  | 
| − | Иными словами,   | + | Иными словами, приведённая стоимость {{---}} это сколько нужно потратить денег, чтобы перевезти единицу жидкости из <tex>u</tex> в <tex>v</tex> (её нужно купить в <tex>u</tex>, перевезти из <tex>u</tex> в <tex>v</tex> и продать в <tex>v</tex>).  | 
{{Лемма  | {{Лемма  | ||
|id=lemma1  | |id=lemma1  | ||
| − | |about=  | + | |about=<tex>1</tex>  | 
|statement=Если <tex>f</tex> {{---}} поток минимальной стоимости, то <tex>\exists \varphi</tex> такое, что <tex>\forall uv: \; c_{f}(uv) > 0 \implies p_{\varphi}(uv) \geqslant 0</tex>.  | |statement=Если <tex>f</tex> {{---}} поток минимальной стоимости, то <tex>\exists \varphi</tex> такое, что <tex>\forall uv: \; c_{f}(uv) > 0 \implies p_{\varphi}(uv) \geqslant 0</tex>.  | ||
|proof=  | |proof=  | ||
| Строка 42: | Строка 54: | ||
{{Лемма  | {{Лемма  | ||
|id=lemma2  | |id=lemma2  | ||
| − | |about=  | + | |about=<tex>2</tex>  | 
|statement=Если стоимости целочисленны и поток <tex>f</tex> {{---}} <tex>\varepsilon</tex>-оптимальный, где <tex>\varepsilon < \dfrac{1}{V}</tex>, то <tex>f</tex> {{---}} поток минимальной стоимости.  | |statement=Если стоимости целочисленны и поток <tex>f</tex> {{---}} <tex>\varepsilon</tex>-оптимальный, где <tex>\varepsilon < \dfrac{1}{V}</tex>, то <tex>f</tex> {{---}} поток минимальной стоимости.  | ||
|proof=    | |proof=    | ||
| Строка 52: | Строка 64: | ||
{{Лемма  | {{Лемма  | ||
|id=lemma3  | |id=lemma3  | ||
| − | |about=  | + | |about=<tex>3</tex>  | 
|statement=Если <tex>f</tex> {{---}} поток не минимальной стоимости, то <tex>\varepsilon^{*}=-\mu^{*}</tex>.  | |statement=Если <tex>f</tex> {{---}} поток не минимальной стоимости, то <tex>\varepsilon^{*}=-\mu^{*}</tex>.  | ||
|proof=  | |proof=  | ||
| Строка 61: | Строка 73: | ||
*Теперь покажем, что <tex>\mu^{*} \leqslant -\varepsilon^{*}</tex>.  | *Теперь покажем, что <tex>\mu^{*} \leqslant -\varepsilon^{*}</tex>.  | ||
:Пусть <tex>p'(uv)=p(uv)-\mu^{*}</tex> для любого <tex>uv \in E_{f}</tex>. Логичным будет также обозначить для некоторого цикла <tex>C</tex> за <tex>\mu'(C)</tex> величину <tex>\dfrac{p'(C)}{\texttt{len}(C)}</tex>. Таким образом, для любого цикла <tex>C</tex>, <tex>\mu'(C)=\mu(C)-\mu^{*}\geqslant 0</tex>.  | :Пусть <tex>p'(uv)=p(uv)-\mu^{*}</tex> для любого <tex>uv \in E_{f}</tex>. Логичным будет также обозначить для некоторого цикла <tex>C</tex> за <tex>\mu'(C)</tex> величину <tex>\dfrac{p'(C)}{\texttt{len}(C)}</tex>. Таким образом, для любого цикла <tex>C</tex>, <tex>\mu'(C)=\mu(C)-\mu^{*}\geqslant 0</tex>.  | ||
| − | :Далее проведем рассуждения, аналогичные доказательству [[#lemma1|леммы   | + | :Далее проведем рассуждения, аналогичные доказательству [[#lemma1|леммы <tex>1</tex>]].  | 
:Добавим вершину <tex>a</tex> и проведем из нее ребро стоимости <tex>0</tex> во все вершины графа <tex>G_{f}</tex>. В качестве <tex>\varphi(u)</tex> выберем стоимость (считая стоимостью функцию <tex>p'</tex>) минимального пути из <tex>a</tex> в <tex>u</tex>.    | :Добавим вершину <tex>a</tex> и проведем из нее ребро стоимости <tex>0</tex> во все вершины графа <tex>G_{f}</tex>. В качестве <tex>\varphi(u)</tex> выберем стоимость (считая стоимостью функцию <tex>p'</tex>) минимального пути из <tex>a</tex> в <tex>u</tex>.    | ||
:Таким образом, <tex>\varphi(v) \leqslant \varphi(u) + p'(uv) = \varphi(u) + p(uv) - \mu^{*}</tex>. Отсюда получаем, что <tex>p_{\varphi}(uv) \geqslant \mu^{*}</tex> для любого ребра <tex>uv</tex> из остаточной сети <tex>E_{f}</tex>, что означает, что <tex>f</tex> {{---}} <tex>(-\mu^{*})</tex>-оптимальный, и, по определению <tex>\varepsilon^{*}</tex>, <tex>\varepsilon^{*} \leqslant -\mu^{*}</tex>.  | :Таким образом, <tex>\varphi(v) \leqslant \varphi(u) + p'(uv) = \varphi(u) + p(uv) - \mu^{*}</tex>. Отсюда получаем, что <tex>p_{\varphi}(uv) \geqslant \mu^{*}</tex> для любого ребра <tex>uv</tex> из остаточной сети <tex>E_{f}</tex>, что означает, что <tex>f</tex> {{---}} <tex>(-\mu^{*})</tex>-оптимальный, и, по определению <tex>\varepsilon^{*}</tex>, <tex>\varepsilon^{*} \leqslant -\mu^{*}</tex>.  | ||
| Строка 68: | Строка 80: | ||
{{Лемма  | {{Лемма  | ||
|id=lemma4  | |id=lemma4  | ||
| − | |about=  | + | |about=<tex>4</tex>  | 
|statement=Отмена цикла минимального среднего веса не увеличивает <tex>\varepsilon^{*}</tex>.  | |statement=Отмена цикла минимального среднего веса не увеличивает <tex>\varepsilon^{*}</tex>.  | ||
|proof=  | |proof=  | ||
:Пусть <tex>C</tex> {{---}} цикл минимального среднего веса, который мы хотим отменить на текущем шаге нашего алгоритма. Перед тем, как мы отменим этот цикл, любое ребро в остаточной сети, в том числе, любое входящее в цикл <tex>C</tex> ребро <tex>uv</tex> удовлетворяет свойству <tex>\varepsilon^{*}</tex>-оптимальности: <tex>p_{\varphi}(uv) \geqslant -\varepsilon^{*}</tex>.    | :Пусть <tex>C</tex> {{---}} цикл минимального среднего веса, который мы хотим отменить на текущем шаге нашего алгоритма. Перед тем, как мы отменим этот цикл, любое ребро в остаточной сети, в том числе, любое входящее в цикл <tex>C</tex> ребро <tex>uv</tex> удовлетворяет свойству <tex>\varepsilon^{*}</tex>-оптимальности: <tex>p_{\varphi}(uv) \geqslant -\varepsilon^{*}</tex>.    | ||
| − | :По [[#lemma3|лемме   | + | :По [[#lemma3|лемме <tex>3</tex>]], <tex>\varepsilon^{*}=-\mu^{*}</tex>, то есть <tex>p_{\varphi}(uv) \geqslant \mu^{*}</tex>. Но поскольку <tex>\mu^{*}</tex> {{---}} средний вес цикла, то <tex>p_{\varphi}(uv) = \mu^{*} = -\varepsilon^{*}</tex>.    | 
:По [[Поток минимальной стоимости #Свойства стоимости|свойству антисимметричности потока]], после отмены цикла <tex>C</tex>, в остаточной сети появятся ребра стоимости <tex>\varepsilon</tex>. Таким образом, свойство <tex>p_{\varphi}(uv) \geqslant -\varepsilon</tex> все еще выполняется.  | :По [[Поток минимальной стоимости #Свойства стоимости|свойству антисимметричности потока]], после отмены цикла <tex>C</tex>, в остаточной сети появятся ребра стоимости <tex>\varepsilon</tex>. Таким образом, свойство <tex>p_{\varphi}(uv) \geqslant -\varepsilon</tex> все еще выполняется.  | ||
}}  | }}  | ||
| Строка 82: | Строка 94: | ||
{{Лемма  | {{Лемма  | ||
|id=lemma5  | |id=lemma5  | ||
| − | |about=  | + | |about=<tex>5</tex>  | 
|statement=Пусть <tex>f</tex> {{---}} некоторый поток, а <tex>f'</tex> {{---}} поток после <tex>E</tex> отмен циклов минимального среднего веса. Тогда <tex>\varepsilon'^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}</tex>, где <tex>\varepsilon'^{*}</tex> {{---}} минимальное <tex>\varepsilon</tex> такое, что поток <tex>f'</tex> <tex>\varepsilon</tex>-оптимальный.  | |statement=Пусть <tex>f</tex> {{---}} некоторый поток, а <tex>f'</tex> {{---}} поток после <tex>E</tex> отмен циклов минимального среднего веса. Тогда <tex>\varepsilon'^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}</tex>, где <tex>\varepsilon'^{*}</tex> {{---}} минимальное <tex>\varepsilon</tex> такое, что поток <tex>f'</tex> <tex>\varepsilon</tex>-оптимальный.  | ||
|proof=  | |proof=  | ||
| − | :Изначально любое ребро <tex>uv</tex> удовлетворяет свойству <tex>p_{\varphi}(uv) \geqslant -\varepsilon^{*}</tex>. Отмена цикла добавляет в остаточную сеть <tex>G_{f}</tex> только ребра положительной приведенной стоимости (см. [[#lemma4|лемму   | + | :Изначально любое ребро <tex>uv</tex> удовлетворяет свойству <tex>p_{\varphi}(uv) \geqslant -\varepsilon^{*}</tex>. Отмена цикла добавляет в остаточную сеть <tex>G_{f}</tex> только ребра положительной приведенной стоимости (см. [[#lemma4|лемму <tex>4</tex>]]) и удаляет из сети <tex>G</tex> как минимум одно ребро. Рассмотрим два случая:  | 
:#Ни один из отмененных циклов не содержал ребер, обладающих неотрицательной приведенной стоимостью. Тогда каждая отмена цикла уменьшает размер допустимого графа <tex>H</tex> и после <tex>E</tex> отмен граф <tex>H</tex> пуст, что означает, что <tex>f'</tex> {{---}} оптимальный поток, то есть <tex>\varepsilon'^{*}=0</tex>.  | :#Ни один из отмененных циклов не содержал ребер, обладающих неотрицательной приведенной стоимостью. Тогда каждая отмена цикла уменьшает размер допустимого графа <tex>H</tex> и после <tex>E</tex> отмен граф <tex>H</tex> пуст, что означает, что <tex>f'</tex> {{---}} оптимальный поток, то есть <tex>\varepsilon'^{*}=0</tex>.  | ||
| − | :#Некоторые из отмененных циклов содержали ребра неотрицательной приведенной стоимости. Пусть впервые такое случилось на <tex>i</tex>-ой итерации, и, соответственно, <tex>C_{i}</tex> {{---}} первый из таких циклов. Для <tex>C_{i}</tex> имеем, что каждое его ребро обладает приведенной стоимостью как минимум <tex>-\varepsilon_{i}^{*}</tex> (при этом <tex>\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} \leqslant \varepsilon^{*}</tex> по [[#lemma4|лемме   | + | :#Некоторые из отмененных циклов содержали ребра неотрицательной приведенной стоимости. Пусть впервые такое случилось на <tex>i</tex>-ой итерации, и, соответственно, <tex>C_{i}</tex> {{---}} первый из таких циклов. Для <tex>C_{i}</tex> имеем, что каждое его ребро обладает приведенной стоимостью как минимум <tex>-\varepsilon_{i}^{*}</tex> (при этом <tex>\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} \leqslant \varepsilon^{*}</tex> по [[#lemma4|лемме <tex>4</tex>]]), хотя бы одно из ребер <tex>C_{i}</tex> обладает неотрицательной приведенной стоимостью и количество ребер в <tex>C_{i}</tex> не превышает <tex>V</tex>. Тогда средний вес этого цикла <tex>\mu(C_{i}) = \mu_{i}^{*} \geqslant -\left(1-\dfrac{1}{V}\right)\varepsilon_{i}^{*} \geqslant - \left(1-\dfrac{1}{V}\right)\varepsilon^{*}</tex>, и <tex>\varepsilon'^{*} \leqslant \varepsilon_{i}^{*} = -\mu_{i}^{*} \leqslant \left(1-\dfrac{1}{V}\right)\varepsilon^{*}</tex>.}}  | 
{{Определение  | {{Определение  | ||
| Строка 102: | Строка 114: | ||
:Покажем теперь, что <tex>f'</tex> не <tex>\varepsilon</tex>-оптимальный.  | :Покажем теперь, что <tex>f'</tex> не <tex>\varepsilon</tex>-оптимальный.  | ||
:Обозначим за <tex>G_{>}</tex> подграф <tex>G</tex> такой, что <tex>G_{>}=(V, \{uv \in E \;|\; f'(uv) > f(uv) \})</tex>. Рассмотрим некоторое ребро <tex>uv</tex> в <tex>G_{>}</tex>. Поскольку <tex>f</tex> и <tex>f'</tex> являются циркуляциями, в <tex>G_{>}</tex> должен содержаться простой цикл <tex>C</tex>, проходящий через <tex>uv</tex>. Поскольку все ребра в <tex>C</tex> {{---}} остаточные, стоимость <tex>C</tex> не меньше <tex>p_{\varphi}(uv) - (\texttt{len}(C)-1)\varepsilon \geqslant 2V\varepsilon - (V-1)\varepsilon > V\varepsilon</tex>.  | :Обозначим за <tex>G_{>}</tex> подграф <tex>G</tex> такой, что <tex>G_{>}=(V, \{uv \in E \;|\; f'(uv) > f(uv) \})</tex>. Рассмотрим некоторое ребро <tex>uv</tex> в <tex>G_{>}</tex>. Поскольку <tex>f</tex> и <tex>f'</tex> являются циркуляциями, в <tex>G_{>}</tex> должен содержаться простой цикл <tex>C</tex>, проходящий через <tex>uv</tex>. Поскольку все ребра в <tex>C</tex> {{---}} остаточные, стоимость <tex>C</tex> не меньше <tex>p_{\varphi}(uv) - (\texttt{len}(C)-1)\varepsilon \geqslant 2V\varepsilon - (V-1)\varepsilon > V\varepsilon</tex>.  | ||
| − | :Теперь рассмотрим цикл <tex>\overline{C}</tex>, который получен из <tex>C</tex> разворотом всех его ребер. Заметим, что <tex>\overline{C}</tex> является циклом в <tex>G_{<}=(V,\{uv \in E \;|\; f'(uv) < f(uv)\})</tex> и, соответственно, циклом в <tex>G_{f}</tex>. По свойству антисимметричности, стоимость <tex>\overline{C}</tex> меньше, чем <tex>-V\varepsilon</tex> и, таким образом, <tex>\mu(\overline{C}) < -\varepsilon</tex>. Откуда по [[#lemma3|лемме   | + | :Теперь рассмотрим цикл <tex>\overline{C}</tex>, который получен из <tex>C</tex> разворотом всех его ребер. Заметим, что <tex>\overline{C}</tex> является циклом в <tex>G_{<}=(V,\{uv \in E \;|\; f'(uv) < f(uv)\})</tex> и, соответственно, циклом в <tex>G_{f}</tex>. По свойству антисимметричности, стоимость <tex>\overline{C}</tex> меньше, чем <tex>-V\varepsilon</tex> и, таким образом, <tex>\mu(\overline{C}) < -\varepsilon</tex>. Откуда по [[#lemma3|лемме <tex>3</tex>]] имеем, что <tex>f'</tex> не <tex>\varepsilon</tex>-оптимален.  | 
}}  | }}  | ||
| Строка 110: | Строка 122: | ||
|proof=  | |proof=  | ||
:Оценка времени работы следует непосредственно из этого утверждения.    | :Оценка времени работы следует непосредственно из этого утверждения.    | ||
| − | :Чтобы доказать его, рассмотрим некоторую группу итераций. Пусть <tex>f</tex> {{---}} поток до первой итерации, а <tex>f'</tex> {{---}} после последней итерации этой группы. Обозначим за <tex>\varepsilon'^{*}</tex> минимальное <tex>\varepsilon</tex> такое, что поток <tex>f'</tex> <tex>\varepsilon</tex>-оптимальный, а за <tex>\varphi'</tex> {{---}} функцию потенциалов такую, что <tex>f'</tex> удовлетворяет свойству <tex>\varepsilon'^{*}</tex>-оптимальности. Выбор <tex>k</tex> и [[#lemma5|лемма   | + | :Чтобы доказать его, рассмотрим некоторую группу итераций. Пусть <tex>f</tex> {{---}} поток до первой итерации, а <tex>f'</tex> {{---}} после последней итерации этой группы. Обозначим за <tex>\varepsilon'^{*}</tex> минимальное <tex>\varepsilon</tex> такое, что поток <tex>f'</tex> <tex>\varepsilon</tex>-оптимальный, а за <tex>\varphi'</tex> {{---}} функцию потенциалов такую, что <tex>f'</tex> удовлетворяет свойству <tex>\varepsilon'^{*}</tex>-оптимальности. Выбор <tex>k</tex> и [[#lemma5|лемма <tex>5</tex>]] дают нам следующее неравенство: <tex>\varepsilon'^{*} \leqslant \varepsilon^{*} \left(1-\dfrac{1}{V} \right)^{V(\log V + 1)} \leqslant \dfrac{\varepsilon^{*}}{2V}</tex>.    | 
| − | :Рассмотрим цикл <tex>C</tex>, отмененный на первой итерации рассматриваемой группы. Поскольку средний вес цикла <tex>C</tex> равен <tex>-\varepsilon^{*}</tex> (см. [[#lemma3|лемму   | + | :Рассмотрим цикл <tex>C</tex>, отмененный на первой итерации рассматриваемой группы. Поскольку средний вес цикла <tex>C</tex> равен <tex>-\varepsilon^{*}</tex> (см. [[#lemma3|лемму <tex>3</tex>]]), некоторое ребро <tex>uv</tex> цикла <tex>C</tex> должно иметь приведенную стоимость <tex>p_{\varphi'}(uv) \leqslant -\varepsilon^{*} \leqslant -2V\varepsilon'^{*}</tex>. Таким образом, поток на ребре <tex>uv</tex> не изменится при итерациях, происходящих после этой группы. Таким образом, по [[#theorem1|теореме]] каждая группа фиксирует поток на независимом ребре.}}  | 
==Алгоритм поиска цикла минимального среднего веса==  | ==Алгоритм поиска цикла минимального среднего веса==  | ||
| Строка 120: | Строка 132: | ||
Тогда, если <tex>C_{max}</tex> и <tex>C_{min}</tex> {{---}} максимальная и минимальная возможные величины среднего веса цикла соответственно, такой алгоритм для вещественных значений весов ребер будет работать за <tex>O\left(\log \dfrac{C_{max}-C_{min}}{\varepsilon} \cdot EV\right)</tex>, где <tex>\varepsilon</tex> {{---}} точность выбора среднего веса цикла.  | Тогда, если <tex>C_{max}</tex> и <tex>C_{min}</tex> {{---}} максимальная и минимальная возможные величины среднего веса цикла соответственно, такой алгоритм для вещественных значений весов ребер будет работать за <tex>O\left(\log \dfrac{C_{max}-C_{min}}{\varepsilon} \cdot EV\right)</tex>, где <tex>\varepsilon</tex> {{---}} точность выбора среднего веса цикла.  | ||
При этом для целочисленных значений на ребрах точность выбора величины среднего веса цикла не может превысить <tex>\dfrac{1}{V}</tex>, что дает нам оценку <tex>O\left(\log (V(C_{max}-C_{min})) \cdot EV\right)</tex>.  | При этом для целочисленных значений на ребрах точность выбора величины среднего веса цикла не может превысить <tex>\dfrac{1}{V}</tex>, что дает нам оценку <tex>O\left(\log (V(C_{max}-C_{min})) \cdot EV\right)</tex>.  | ||
| + | |||
| + | ====Псевдокод====  | ||
| + | |||
| + |   '''func''' findMinCycleBinarySearch('''int''' l, '''int''' r)  | ||
| + |       <font color="green">// находим среднюю величину <tex>m</tex></font>  | ||
| + |       m = (l + r) / 2  | ||
| + |       <font color="green">// вычитаем её из веса каждого ребра в сети</font>  | ||
| + |       '''for''' e '''in''' edges  | ||
| + |           e.weight -= m  | ||
| + |       '''while''' l > r - 1  | ||
| + |       <!-----<font color="green">// добавляем мнимую вершину <tex>s</tex> и проводим рёбра нулевого веса в каждую вершину графа</font>--------->  | ||
| + |           '''if''' <tex>\exists</tex>C : M(C) < 0 <!--- cho-t xz za4em C: mb exists? eee ugadala)0))--->  | ||
| + |               <font color="green">// если есть отрицательный цикл, то веса циклов находятся в диапазоне <tex>[l;m]</tex>  | ||
| + |               // рассмотрим этот промежуток</font>  | ||
| + |               findMinCycleBinarySearch (l, m)  | ||
| + |           '''else'''  | ||
| + |               <font color="green">// иначе запускаем двоичный поиск на отрезке <tex>[m;r]</tex></font>  | ||
| + |               findMinCycleBinarySearch (m, r)  | ||
===Продвинутый алгоритм===  | ===Продвинутый алгоритм===  | ||
| − | Добавим к нашему графу вершину <tex>s</tex> и   | + | Добавим к нашему графу вершину <tex>s</tex> и рёбра из неё во все остальные вершины.  | 
Запустим [[алгоритм Форда-Беллмана]] и попросим его построить нам квадратную матрицу со следующим условием: <tex>d[i][u]</tex> {{---}} длина минимального пути от <tex>s</tex> до <tex>u</tex> ровно из <tex>i</tex> ребер.  | Запустим [[алгоритм Форда-Беллмана]] и попросим его построить нам квадратную матрицу со следующим условием: <tex>d[i][u]</tex> {{---}} длина минимального пути от <tex>s</tex> до <tex>u</tex> ровно из <tex>i</tex> ребер.  | ||
Тогда длина оптимального цикла <tex>\mu^{*}</tex> минимального среднего веса вычисляется как <tex>\min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}</tex>.  | Тогда длина оптимального цикла <tex>\mu^{*}</tex> минимального среднего веса вычисляется как <tex>\min\limits_{u} {\max\limits_{k} {\dfrac{d[n][u]-d[k][u]}{n-k}}}</tex>.  | ||
| Строка 133: | Строка 163: | ||
====Псевдокод====  | ====Псевдокод====  | ||
| − |    '''func'''   | + |    '''func''' findMinCycle('''Graph''' G)  | 
| − | + |       <font color="green">// вводим мнимую вершину <tex>s</tex>, от которой проведём рёбра нулевого веса в каждую вершину графа</font>  | |
| − | + |       '''Node''' s  | |
| − | + |       '''Edge[]''' e  | |
| − |        '''  | + |       insert(s)     | 
| − | + |       i = 0                                        | |
| − |        <tex>  | + |        '''for''' u '''in''' G  | 
| + |           e[i].begin = s  | ||
| + |           e[i].end = u  | ||
| + |           e[i].weight = 0  | ||
| + |           i++  | ||
| + |       <font color="green">// строим матрицу кратчайших расстояний, запустив алгоритм Форда-Беллмана из вершины <tex>s</tex></font>  | ||
| + |       fordBellman(s)  | ||
| + |       <font color="green">// <tex>m</tex> {{---}} длина оптимального цикла</font>  | ||
| + |        m = <tex>\min\limits_{u} {\max\limits_{k} }</tex>((d[n][u] - d[k][u]) / (n - k))  | ||
| + |       <!-----<font color="green">// запомнив значения <tex>u</tex> и <tex>k</tex>, дающих оптимальный результат, найдём цикл</font>--------->  | ||
| + |       <!----чуть не забыла про отступы, дура тупая----->  | ||
==См. также==  | ==См. также==  | ||
Текущая версия на 19:26, 4 сентября 2022
В статье описывается один из сильно полиномиальных алгоритмов решения задачи о поиске потока минимальной стоимости.
Содержание
Алгоритм
Приведенный алгоритм основан на идее алгоритма Клейна отмены цикла отрицательного веса. Выбор цикла минимального среднего веса вместо случайного делает алгоритм сильно полиномиальным.
| Определение: | 
| Сильно полиномиальными (англ. strongly polynomial) в контексте данной задачи называются алгоритмы, чья сложность полиномиально зависит от и . | 
Описание
Обозначим как остаточную пропускную способность цикла при протекании в сети потока . Cтоимость цикла обозначим за , а длину (число входящих в него ребер) — за .
| Определение: | 
| Средним весом (англ. mean weight) цикла будем называть отношение его стоимости к его длине | 
Данный алгоритм заключается в последовательной отмене циклов минимального среднего веса в остаточной сети посредством их насыщения. Алгоритм работает до тех пор, пока минимальный средний вес циклов не окажется положительным, что будет означать, что поток минимальной стоимости найден.
Более формально:
- Шаг . Рассмотрим некоторый поток .
 - Шаг . Найдем цикл , обладающий наименьшим средним весом. Если , то — поток минимальной стоимости и алгоритм завершается.
 - Шаг . Отменим цикл , пустив по нему максимально возможный поток: . Перейдем к шагу .
 
Сложность
Для сетей с целочисленными стоимостями на ребрах , с вещественными — . В обоих случаях времени тратится на поиск цикла минимального среднего веса.
Псевдокод
 Edge[] findMin(Graph G)
     while f
         // найдём M(C) — вес минимального цикла
         C = c : M(c) =  M(c)  
         if M(C)  0
             // Если величина M(C) положительна, то мы нашли f — поток минимальной стоимости, на этом алгоритм завершается
             return f                             
         else
             // в противном случае отменяем цикл
             f += c_f * f(C)
Корректность
Пусть — поток минимальной стоимости. Введём на нашей сети функцию потенциалов .
| Определение: | 
| Приведённой стоимостью (англ. reduced cost) ребра назовем следующую величину: . | 
Иными словами, приведённая стоимость — это сколько нужно потратить денег, чтобы перевезти единицу жидкости из в (её нужно купить в , перевезти из в и продать в ).
| Лемма (): | 
Если  — поток минимальной стоимости, то  такое, что .  | 
| Доказательство: | 
 
 
  | 
| Определение: | 
| Будем говорить, что поток — -оптимальный (англ. -optimal), если такая, что . | 
| Лемма (): | 
Если стоимости целочисленны и поток  — -оптимальный, где , то  — поток минимальной стоимости.  | 
| Доказательство: | 
 
  | 
Обозначим за минимальную величину среди средних весов циклов для потока , а за минимальное такое, что поток — -оптимальный.
| Лемма (): | 
Если  — поток не минимальной стоимости, то .  | 
| Доказательство: | 
 
 
 
 
  | 
| Лемма (): | 
Отмена цикла минимального среднего веса не увеличивает .  | 
| Доказательство: | 
  | 
| Определение: | 
| Допустимым графом (англ. admissible graph) будем называть такой подграф остаточной сети, что он включает только ребра отрицательной приведенной стоимости. | 
| Лемма (): | 
Пусть  — некоторый поток, а  — поток после  отмен циклов минимального среднего веса. Тогда , где  — минимальное  такое, что поток  -оптимальный.  | 
| Доказательство: | 
  | 
| Определение: | 
| -фиксированным (англ. -fixed) будем называть ребро, поток через которое неизменен для любых -оптимальных потоков в сети. | 
| Теорема: | 
Пусть поток  является -оптимальным с функцией потенциалов . Также пусть для некоторого ребра . Тогда ребро  -фиксировано.  | 
| Доказательство: | 
 
 
  | 
| Лемма (доказательство оценки времени работы алгоритма в случае вещественных стоимостей): | 
Пусть . Разобьем работу алгоритма на группы по  последовательных итераций. Утверждается, что каждая группа фиксирует поток на независимом ребре , то есть итерации из другой группы не меняют величину .  | 
| Доказательство: | 
  | 
Алгоритм поиска цикла минимального среднего веса
Наивный способ
Устроим двоичный поиск. Установим нижнюю и верхнюю границы величины среднего веса цикла и соответственно, вычислим серединное значение и отнимем полученную величину от всех ребер сети. Если теперь в нашей сети есть отрицательный цикл (этот факт можно проверить при помощи алгоритма Форда-Беллмана), значит существует цикл с меньшим средним весом, чем . Тогда продолжим поиск среди значений в диапазоне от до , иначе — от до .
Тогда, если и — максимальная и минимальная возможные величины среднего веса цикла соответственно, такой алгоритм для вещественных значений весов ребер будет работать за , где — точность выбора среднего веса цикла. При этом для целочисленных значений на ребрах точность выбора величины среднего веса цикла не может превысить , что дает нам оценку .
Псевдокод
 func findMinCycleBinarySearch(int l, int r)
     // находим среднюю величину 
     m = (l + r) / 2
     // вычитаем её из веса каждого ребра в сети
     for e in edges
         e.weight -= m
     while l > r - 1
         if C : M(C) < 0 
             // если есть отрицательный цикл, то веса циклов находятся в диапазоне 
             // рассмотрим этот промежуток
             findMinCycleBinarySearch (l, m)
         else
             // иначе запускаем двоичный поиск на отрезке 
             findMinCycleBinarySearch (m, r)
Продвинутый алгоритм
Добавим к нашему графу вершину и рёбра из неё во все остальные вершины. Запустим алгоритм Форда-Беллмана и попросим его построить нам квадратную матрицу со следующим условием: — длина минимального пути от до ровно из ребер. Тогда длина оптимального цикла минимального среднего веса вычисляется как .
Достаточно будет доказать это правило для , так как для других можно просто отнять эту величину от всех ребер и получить снова случай с .
Чтобы найти цикл после построения матрицы , запомним, при каких и достигается оптимальное значение , и, используя , поднимемся по указателям предков. Как только мы попадем в уже посещенную вершину — мы нашли цикл минимального среднего веса.
Этот алгоритм работает за [2].
Псевдокод
 func findMinCycle(Graph G)
     // вводим мнимую вершину , от которой проведём рёбра нулевого веса в каждую вершину графа
     Node s
     Edge[] e
     insert(s)   
     i = 0                                      
     for u in G
         e[i].begin = s
         e[i].end = u
         e[i].weight = 0
         i++
     // строим матрицу кратчайших расстояний, запустив алгоритм Форда-Беллмана из вершины 
     fordBellman(s)
     //  — длина оптимального цикла
     m = ((d[n][u] - d[k][u]) / (n - k))
См. также
- Использование потенциалов Джонсона при поиске потока минимальной стоимости
 - Сведение задачи о назначениях к задаче о потоке минимальной стоимости
 
Примечания
Источники информации
- Лекция 14 | Дополнительные главы алгоритмов | Андрей Станкевич | CSC | Лекториум
 - A.V.Goldberg and R.E.Tarjan — Finding Minimum-Cost Circulations by Cancelling Negative Cycles (Journal of the Association for Computing Machinery. Vol. 36, No. 4. October 1989. pp. 873-886.)
 - Lecture by M.X.Goemans on Goldberg-Tarjan Min-Cost Circulation Algorithm