Метод Форда–Фалкерсона или алгоритм Форда–Фалкерсона ( FFA ) — это жадный алгоритм , который вычисляет максимальный поток в потоковой сети . Иногда его называют «методом» вместо «алгоритма», поскольку подход к поиску увеличивающихся путей в остаточном графе не полностью определен [1] или определен в нескольких реализациях с разным временем выполнения. [2] Он был опубликован в 1956 году Л. Р. Фордом-младшим и Д. Р. Фулкерсоном . [3] Название «Форд–Фалкерсон» часто также используется для алгоритма Эдмондса–Карпа , который является полностью определенной реализацией метода Форда–Фалкерсона.
Идея алгоритма заключается в следующем: пока есть путь от источника (начальный узел) до стока (конечный узел), с доступной пропускной способностью на всех ребрах пути, мы отправляем поток по одному из путей. Затем мы находим другой путь и так далее. Путь с доступной пропускной способностью называется увеличивающим путем .
Пусть будет графом, и для каждого ребра от u до v пусть будет пропускная способность и будет поток. Мы хотим найти максимальный поток от источника s до стока t . После каждого шага в алгоритме сохраняется следующее:
Это означает, что поток через сеть является законным потоком после каждого раунда в алгоритме. Мы определяем остаточную сеть как сеть с пропускной способностью и без потока. Обратите внимание, что может случиться так, что поток из v в u разрешен в остаточной сети, хотя запрещен в исходной сети: если и тогда .
Алгоритм Форда–Фалкерсона
Путь на шаге 2 можно найти, например, с помощью поиска в ширину (BFS) или поиска в глубину в . Первый известен как алгоритм Эдмондса–Карпа .
Если больше путей на шаге 2 не найдено, s не сможет достичь t в остаточной сети. Если S — множество узлов, достижимых s в остаточной сети, то общая пропускная способность в исходной сети ребер от S до остатка V , с одной стороны, равна общему потоку, который мы нашли от s до t , а с другой стороны, служит верхней границей для всех таких потоков. Это доказывает, что найденный нами поток является максимальным. См. также теорему о максимальном потоке и минимальном разрезе .
Если граф имеет несколько источников и стоков, действуем следующим образом: Предположим, что и . Добавляем новый источник с ребром из в каждый узел , с пропускной способностью . И добавляем новый сток с ребром из каждого узла в , с пропускной способностью . Затем применяем алгоритм Форда–Фалкерсона.
Также, если узел u имеет ограничение емкости , мы заменяем этот узел двумя узлами , и ребром , с емкостью . Затем применяем алгоритм Форда–Фалкерсона.
Добавляя путь увеличения потока к потоку, уже установленному в графе, максимальный поток будет достигнут, когда в графе больше не будет найдено путей увеличения потока. Однако нет никакой уверенности, что эта ситуация когда-либо будет достигнута, поэтому лучшее, что можно гарантировать, — это то, что ответ будет правильным, если алгоритм завершится. В случае, если алгоритм будет работать вечно, поток может даже не сходиться к максимальному потоку. Однако эта ситуация возникает только с иррациональными значениями потока. [4] Когда пропускные способности являются целыми числами, время выполнения Форда–Фалкерсона ограничено (см. обозначение большого О ), где — количество ребер в графе, а — максимальный поток в графе. Это происходит потому, что каждый путь увеличения потока может быть найден за время и увеличивает поток на целую величину не менее , с верхней границей .
Разновидностью алгоритма Форда–Фалкерсона с гарантированным завершением и временем выполнения, не зависящим от максимального значения потока, является алгоритм Эдмондса–Карпа , который выполняется во времени.
Следующий пример показывает первые шаги Форда–Фалкерсона в потоковой сети с 4 узлами, источником и стоком . Этот пример показывает наихудшее поведение алгоритма. На каждом шаге по сети отправляется только поток. Если бы вместо этого использовался поиск в ширину, потребовалось бы всего два шага.
Рассмотрим сеть потоков, показанную справа, с источником , стоком , пропускными способностями ребер , и , а также пропускной способностью всех остальных ребер некоторым целым числом . Константа была выбрана таким образом, что . Мы используем увеличивающиеся пути в соответствии со следующей таблицей, где , и .
Обратите внимание , что после шага 1, а также после шага 5 остаточные пропускные способности ребер , и имеют вид , и , соответственно, для некоторых . Это означает, что мы можем использовать увеличивающие пути , и бесконечно много раз, и остаточные пропускные способности этих ребер всегда будут иметь один и тот же вид. Общий поток в сети после шага 5 равен . Если мы продолжим использовать увеличивающие пути, как указано выше, общий поток сойдется к . Однако обратите внимание, что существует поток значения , отправляя единицы потока по , 1 единицу потока по и единицы потока по . Поэтому алгоритм никогда не останавливается, и поток даже не сходится к максимальному потоку. [5]
Другой незавершающийся пример, основанный на алгоритме Евклида, приведен Бэкманом и Хюином (2018), где они также показывают, что худшее время выполнения алгоритма Форда-Фалкерсона в сети с порядковыми числами составляет .
импортные коллекцииКласс График : """ Этот класс представляет собой ориентированный граф, использующий Представление матрицы смежности. """ def __init__ ( self , graph ): self.graph = график # остаточный график self.row = len ( график ) определение bfs ( self , s , t , parent ): """ Возвращает true, если есть путь из источник «s» для стока «t» в остаточном графе. Также заполняет parent[] для хранения пути. """ # Отметить все вершины как непосещенные посещенный = [ Ложь ] * сам . строка # Создать очередь для BFS очередь = коллекции . дек () # Отметить исходный узел как посещенный и поставить его в очередь очередь . добавить ( ы ) посетил [ s ] = Правда # Стандартный цикл BFS пока очередь : u = очередь . popleft () # Получить все смежные вершины выведенной из очереди вершины u # Если соседний не был посещен, то отметьте его # посетил и поставил в очередь для ind , val в enumerate ( self . graph [ u ]): если ( visited [ ind ] == False ) и ( val > 0 ): очередь . добавить ( инд .) посетил [ инд ] = Правда родитель [ инд ] = u # Если мы достигли приемника в BFS, начиная с источника, то возвращаемся # правда, иначе ложь вернуться посетил [ t ] # Возвращает максимальный поток из s в t в заданном графе def edmonds_karp ( сам , источник , приемник ): # Этот массив заполняется BFS и для хранения пути родитель = [ - 1 ] * сам . строка max_flow = 0 # Изначально потока нет # Увеличивайте поток, пока есть путь от источника к приемнику в то время как self.bfs ( источник , приемник , родитель ) : # Найти минимальную остаточную емкость ребер вдоль # путь заполнен BFS. Или можно сказать найти максимальный поток # по найденному пути. path_flow = float ( "Inf" ) с = раковина в то время как s != источник : path_flow = min ( path_flow , self . graph [ parent [ s ]][ s ]) с = родитель [ с ] # Добавить поток пути к общему потоку максимальный_поток += путь_потока # обновить остаточные емкости ребер и обратные ребра # по пути в = раковина в то время как v != источник : u = родитель [ v ] self.graph [ u ] [ v ] - = path_flow сам.граф [ v ] [ u ] + = path_flow v = родитель [ v ] вернуть максимальный_поток
{{cite book}}
: CS1 maint: multiple names: authors list (link)Медиа, связанные с алгоритмом Форда-Фалкерсона на Wikimedia Commons