
4. Алгоритм Форда-Фалкерсона.
Метод заключается в поиске возможных путей из AS в AT, увеличивающих поток. За начальный выбирается любой произвольный поток в графе, в частности нулевой.
Поиск выполняют в два этапа.
На первом этапе вершинам присваивают специальные пометки, указывающие направление возможного увеличения отдельных дуговых потоков; на втором – производят изменение потока в графе.
Рассмотрим работу алгоритма на примере графа с одним источником aS и одним стоком at , обобщив затем его для задач с несколькими AS и AT.
Расстановка меток
На первом этапе каждая вершина графа находится в одном из трех состояний: «не помечена», «помечена, но не просмотрена», «помечена и просмотрена».
Пометка любой вершины графа aj состоит из двух частей: первая часть указывает индекс вершины, из которой можно послать поток в рассматриваемую aj, вторая – максимальную величину, на которую можно увеличить поток из aS в aj без нарушения ограничений на пропускные способности дуг. Сначала все вершины не помечены.
Пометки расставляют, начиная с источника aS, который получает пометку [S+, ε(S) = ∞] , что указывает на возможность посылки неограниченного сверху потока из aS в aj . Вершина aS считается помеченной, но не просмотренной.
Пусть имеется некоторая помеченная, но не просмотренная вершина aj, имеющая пометку [i+, ε(j)] или [i-, ε(j)] . Знак в первой части пометки указывает направление дугового потока: если i+ – приращение потока в дуге bij совпадает на втором этапе с направлением первоначального потока дуги, если i- – приращение потока в дуге bij на втором этапе, противоположное направлению первоначального потока. Из множества соседних с aj вершин Гaj выделим подмножество AK непомеченных вершин, для которых дуговой поток xjk меньше пропускной способности cjk . Припишем каждой соседней вершине ag ∈ Ak пометку [j+, ε(g)], где ε(g) = min[ε(j); (cig - xig)].
Выделим подмножество Ah ⊂ Гaj \ Ak непомеченных вершин, для которых xhj > 0, то есть поток «идет» в противоположном направлении.
Припишем каждой последующей соседней вершине af ∈ Ah пометку [j-, ε(f)], где ε(f) = min[ε(j); (xfj + cfj)]. В результате все соседние с aj вершины, которые могут получить пометки, оказываются помеченными, но не просмотренными. А вершина aj – помеченной и просмотренной.
Продолжаем приписывать пометки вершинам соседним с помеченными и не просмотренными узлами, до тех пор, пока либо сток aT не будет помечен, либо не будет ни одной вершины, которая могла бы быть помечена, и сток aT окажется без пометки. Если aT не получает пометки, то дальнейшее увеличение потока в сети невозможно, то есть исходный поток максимален. Иначе переходим ко второму этапу – изменению потока в сети.
Увеличение потока
Пусть по результатам первого этапа сток aT получил метку [p+, ε(T)] . В этом случае заменяем xPT на (xPT + ε(T)). Если же сток получит пометку [p-, ε(T)] , то xPT заменяем (xPT - ε(T)).
Переходим к предыдущей вершине aP. Если она имеет пометку [p+, ε(T)], то xjT заменяем на (xjT + ε(T)). Переходим к вершине aj и т. д.
Процесс изменения потока продолжается до прихода в источник aS. После этого все старые пометки стираются, и делается попытка вновь увеличить поток в графе (переходим к первому этапу алгоритма).
АЛГОРИТМ
Расстановка пометок
Присвоить вершине S (источнику) пометку [S+, ε(S) = ∞]. Вершине S присвоена пометка и она просмотрена, все остальные вершины без пометок.
Взять некоторую непросмотренную вершину ai с пометкой; пусть ее пометка будет [±i, ε(j)].
Каждой непомеченной вершине aj ∈ Гaj, для которой xij < cij, присвоить [+i, ε(j)], где ε(j) = min[ε(j); (cij - xij)].
Каждой непомеченной вершине aj ∈ Г-1ai, для которой xij > 0, присвоить пометку [-i, ε(j)], где ε(j) = min[ε(j); xij].
Теперь вершина ai и помечена, и просмотрена, а вершины aj, пометки которым присвоены в а) и b), являются непросмотренными. Обозначить, что вершина ai просмотрена.
Повторить 2 до тех пор, пока либо сток T будет помечен, и тогда перейти к 4, либо T не будет помечен и никаких других пометок нельзя будет расставить. В этом случае алгоритм заканчивает работу с максимальным вектором потока X. Идти к 7.
Увеличение потока
Положить j = T и идти к 5.
a) Если пометка в вершине aj имеет вид [+i, ε(j)], то изменить поток вдоль дуги biT с xiT на (xiT + ε(T)).
b) Если пометка в вершине aj имеет вид [-i, ε(j)], то изменить поток вдоль дуги biT с xiT на (xiT - ε(T)).
Если ai = S , то стереть все пометки и вернуться к шагу 1, чтобы вновь начать расставлять пометки, но используя уже улучшенный поток, найденный на шаге 5. Если ai ≠ S , то взять ai = a(i-1) и вернуться к шагу 5.
Конец работы алгоритма