Циркуляция потока — различия между версиями
Lehanyich (обсуждение | вклад) |
Shersh (обсуждение | вклад) м (→Псевдокод) |
||
Строка 26: | Строка 26: | ||
==Псевдокод== | ==Псевдокод== | ||
'''function''' circulation(<tex>V,E</tex>) | '''function''' circulation(<tex>V,E</tex>) | ||
− | <tex>G=\varnothing</tex> | + | <tex>G=\varnothing</tex> <font color=green>// пустой граф, вершины s и t - исток и сток</font> |
'''for''' <tex>e : e\in E</tex> <font color=green>// конструктор ребра принимает 4 параметра: две инцидентные ребру вершины, величину потока через это ребро и пропускную способность</font> | '''for''' <tex>e : e\in E</tex> <font color=green>// конструктор ребра принимает 4 параметра: две инцидентные ребру вершины, величину потока через это ребро и пропускную способность</font> | ||
<tex>t</tex> = Edge(<tex>s</tex>, <tex>e</tex>.to, <tex>0</tex>, <tex>e</tex>.min_cap) | <tex>t</tex> = Edge(<tex>s</tex>, <tex>e</tex>.to, <tex>0</tex>, <tex>e</tex>.min_cap) |
Версия 17:43, 7 января 2016
<wikitex>
Определение: |
Поток нулевой величины в сети $G(V, E)$ называется циркуляцией (англ. circulation problem). Каждое ребро $e_i$ имеет $l_i$ и $c_i$ — минимальная и максимальная пропускная способности соответственно. Необходимо выяснить, существует ли в этой сети циркуляция, удовлетворяющая пропускным способностям рёбер. |
Иначе говоря, закон сохранения потока должен выполняться для всех вершин графа, а значит нет нужды в истоке и стоке. Когда все $l_i$ равны $0$, достаточно пустить поток нулевой величины из каждой вершины, что и будет ответом. Поэтому далее в графе будут существовать ребра с положительно нижней пропускной способностью. </wikitex>
Решение
<wikitex>Для решения этой задачи заменим исходную сеть $G$ на $G'$ следующим образом. Сначала добавим в граф вершины $s$ — исток и $t$ — сток. Для каждого ребра $e_i = v_{from} \xrightarrow{l_i, c_i} v_{to}$ добавим ребра $s \xrightarrow{0, l_i} v_{to}$ и $u_{from} \xrightarrow{0, l_i} t$, а также сделаем в ребре $e_i$ изменения: $c_i = c_i - l_i, l_i = 0$ (см. рисунок 2).
Каждое ребро изначального графа заменяется на три новых. Если по ребру $e_i = (v_{from}, v_{to})$ в исходной сети протекает поток $l_i \leqslant f_i \leqslant c_i$, то в новой сети по ребру $(s, v_{to})$ должен течь поток, равный $l_i$, то есть его пропускной способности. Поток, который вытекает из $v_{from}$ по ребру в $G$, заменяется на поток, который протекает по ребрам $(v_{from}, v_{to})$ и $(v_{from}, t)$ (поскольку сумма их пропускных способностей в полученном графе равна $c_i$). Аналогично, для вершины $v_{to}$ суммарный входящий поток не изменился. Таким образом, любой допустимый поток по любому ребру в изначальном графе можно распределить между тремя ребрами в полученном графе. Заметим, что в сети $G'$ все $l_i = 0$, то есть мы имеем обыкновенную сеть.
Требовалось найти циркуляцию в исходной сети, а значит проверить существование потока, для которого выполнено равенство
для всех вершин графа. Это равносильно существованию потока между вершинами $s$ и $t$ в сети $G'$, который полностью насытит ребра, исходящие из истока. Действительно, этот поток в исходном графе насытит $i$-ое ребро как минимум на $l_i$, что и является необходимым требованием. Если этот поток существует, то будет выполнено:- $\sum\limits_v f(u,v)=0,$ где $u \in V'-\{s,t\}, v \in V'$, то есть для всех исходных вершин;
- В $G': f_i \leqslant c_i - l_i \Rightarrow 0 \leqslant f_i \leqslant c_i - l_i \Rightarrow l_i \leqslant f_i + l_i \leqslant c_i$, что удовлетворяет всем ограничениям.
Значит, этот поток и есть циркуляция.
Запустим в новой сети один из алгоритмов поиска максимального потока. Если он не смог полностью насытить все ребра их истока, то и никакой другой по величине поток этого сделать не сможет, значит, циркуляции нет. Для получения величин потоков вдоль каждого ребра в изначальной сети достаточно прибавить к потокам вдоль ребер в сети $G'$ соответствующие значения минимальной пропускной способности. </wikitex>
Псевдокод
function circulation() // пустой граф, вершины s и t - исток и сток for // конструктор ребра принимает 4 параметра: две инцидентные ребру вершины, величину потока через это ребро и пропускную способность = Edge( , .to, , .min_cap) = Edge( .from, .to, , .cap - .min_cap) = Edge( .from, , , .min_cap) maxFlow = getMaxFlow( ) // наибольший поток в графе G for and .from if ( ) .cap // если для текущего ребра flow < cap return false return true