В информатике алгоритм Эдмондса–Карпа представляет собой реализацию метода Форда–Фалкерсона для вычисления максимального потока в потоковой сети за время. Алгоритм был впервые опубликован Ефимом Диницем в 1970 году [1] [2] и независимо опубликован Джеком Эдмондсом и Ричардом Карпом в 1972 году [3] . Алгоритм Диница включает дополнительные методы, которые сокращают время выполнения до . [2]
Алгоритм идентичен алгоритму Форда-Фалкерсона , за исключением того, что порядок поиска при поиске увеличивающего пути определен. Найденный путь должен быть кратчайшим путем, имеющим доступную пропускную способность. Его можно найти с помощью поиска в ширину , где мы применяем вес 1 к каждому ребру. Время выполнения находится путем показа того, что каждый увеличивающий путь может быть найден за время, что каждый раз, когда хотя бы одно из ребер становится насыщенным (ребро, которое имеет максимально возможный поток), что расстояние от насыщенного ребра до источника вдоль увеличивающего пути должно быть больше, чем в прошлый раз, когда оно было насыщено, и что длина не превышает . Другое свойство этого алгоритма заключается в том, что длина кратчайшего увеличивающего пути монотонно увеличивается. Доступное доказательство есть в Введении в алгоритмы . [4]
Алгоритм EdmondsKarp имеет входные данные : graph (graph[v] должен быть списком ребер, выходящих из вершины v в исходном графе , и соответствующих им построенных обратных ребер , которые используются для обратного потока. Каждое ребро должно иметь пропускную способность 'cap', поток, источник 's' и сток 't' в качестве параметров, а также указатель на обратное ребро 'rev'.) s (Исходная вершина) t (Стоковая вершина) выход : поток (Значение максимального потока) flow := 0 (Инициализируем flow нулем) repeat (Запускаем поиск в ширину (bfs), чтобы найти кратчайший путь st. Мы используем 'pred' для хранения ребра, взятого для достижения каждой вершины, чтобы впоследствии можно было восстановить путь) q := queue () q.push(s) pred := array (graph.length) пока не пустой(q) и pred[t] = null текущ := q.pop() для ребра e в graph[cur] сделать , если pred[et] = null и et ≠ s и e.cap > e.flow тогда пред[ет] := е q.push(et) если нет (pred[t] = null) тогда (Мы нашли увеличивающийся путь. Посмотрим, какой поток мы можем отправить) df := ∞ for (e := pred[t]; e ≠ null; e := pred[es]) do df := min (df, e.cap - e.flow) (И обновить ребра на эту величину) for (e := pred[t]; e ≠ null; e := pred[es]) do эл.поток := эл.поток + df e.rev.flow := e.rev.flow - df поток := поток + df пока pred[t] = null (т.е. пока не будет найден дополнительный путь) обратный поток
Дана сеть из семи узлов, источника A, приемника G и пропускных способностей, как показано ниже:
В парах, написанных по краям, — текущий поток, а — емкость. Остаточная емкость от до — это , общая емкость, за вычетом уже использованного потока. Если чистый поток от до отрицателен, он вносит вклад в остаточную емкость.
Обратите внимание, что длина увеличивающегося пути, найденного алгоритмом (красным), никогда не уменьшается. Найденные пути являются кратчайшими из возможных. Найденный поток равен пропускной способности через минимальный разрез в графе, разделяющий источник и сток. В этом графе есть только один минимальный разрез, разделяющий узлы на множества и , с пропускной способностью
{{cite book}}
: CS1 maint: multiple names: authors list (link)