:: алгоритмы  и методы :: :: олимпиадные задачи :: :: связь :: :: о сайте ::
Путь: Математика » Графы и маршруты » Алгоритмы нахождения максимального потока » Алгоритм Карзанова
  Алгоритм Карзанова



Алгоритм Карзанова

Алгоритм Карзанова.

 

Карзанову в 1974г удалось, с помощью модификации алгоритма Диница, добиться оценки быстродействия O(n3). Им также впервые было введено понятие “предпотока”. Дадим следующие определения:

 

Путь Lv,t из вершины v в сток t называется блокированным, если он содержит хотя бы одну насыщенную дугу.

Вершина (дуга) блокирована, если блокирован любой проходящей через нее путь.

Поток f в Sk называется тупиковым, если блокирован источник s.

Предпотоком назовем поток g, удовлетворяющий 4-м условиям:

 

1.      0 ≤ g(u) ≤ ck(u), где u – дуга Sk сети, ck(u) – ее пропускная способность.

2.      Для любой вершины v  Vk \ {s, t}, div (v) ≤ 0.

3.      если div (v) < 0, то vg-блокирована.

4.      источник s g-блокирован.

 

Согласно теореме, доказательство которой приведено в [7], если на i-ом этапе увеличить поток сети с помощью тупикового потока вспомогательной сети, то все кратчайшие увеличивающие пути длины ki будут исчерпаны, и алгоритм перейдет на следующий этап. Это значит, что последовательное построение псевдомаксимальных потоков в Sk сети, может быть заменено поиском тупикового потока. Далее рассматривается алгоритм построения тупикового потока в Sk сети.

 

Для работы необходимы следующие структуры данных:

A(v) – список исходящих из вершины v дуг. Строится для каждой вершины => n списков.

Q(v) – список “добавок” предпотока на дугах, входящих в вершину v. Добавка должна содержать информацию о величине добавки (q(u) > 0) и адрес (либо любой другой идентификатор) дуги u. Необходимо n таких списков. Список Q может содержать несколько добавок, относящихся к одной и той же дуге u.

g(u) – список из m элементов (одномерный массив), содержит текущие значения потока g на дугах u. Отметим, что g(u) = ∑ q(u) из Q(v), где v – конец дуги u.

Dv(v) - список из n элементов (одномерный массив), содержит div (v) для всех вершин v.

D – список дефицитных вершин.

 

Инициализация.

Дана Sk сеть. На всех дугах u исходящих из источника s увеличим поток g на величины, равные пропускным способностям этих дуг (изменяем g(u)). Для всех v смежных с s Dv(v) = - ck(s, v), а в Q(v) заносится добавка q(u) = ck(u). Для остальных вершин Dv(v) = 0, списки Q(v) – пустые. D – пуст. Поток g на данный момент не является предпотоком, т.к. не удовлетворяет 3-му условию. Далее производится процедура “Достройки” (будет рассмотрена позднее), которая превратит g в предпоток и заполнит список D.

 

Нахождение тупикового потока Sk сети – итеративный процесс. На каждой итерации выполняются 2 процедуры: “балансирование” и “достройка”. Достройка производится только в случае необходимости, балансирование – всегда. Тупиковый поток будет построен, как только список дефицитных вершин D станет пустым.

 

Балансирование.

Перед началом балансирования g – всегда предпоток. Балансирование производится на дефицитных вершинах D максимального ранга (максимально удаленных от источника s). Заметим, что по построению, вершины в списке D упорядочены по возрастанию рангов (за исключением случая, который будет оговорен позднее), поэтому, чтобы перебрать все дефицитные вершины максимального ранга, нужно просматривать элементы с конца списка D, до тех пор, пока ранг не изменится.

Балансирование вершины v заключается в получении div(v) = 0, с помощью изменения величины g на входящих в v дугах. Для этого берется элемент q(u) из Q(v), его значение необходимо уменьшить на y = min{q(u), -div(v)}. Если после уменьшения div(v) все еще < 0, то q(u) = 0. Удаляем q(u) (в [7] доказано, что можно и не удалять) из Q(v) и берем следующий элемент Q(v). Как только div(v) = 0, балансировка в вершине v прекращается (вершина v удаляется из D) и начинается балансировка следующей вершины. При изменении уменьшении q(u) также должны производится следующие изменения: g(u) := g(u) – y, Dv(v) := Dv(v) + y, Dv(v’) := Dv(v’) – y, где v’ – вершина, из которой исходит дуга u. До уменьшения q(u), Dv(v’) ≤ 0. Если Dv(v’) было < 0, то v’ уже есть в списке D и никаких дополнительных действий предпринимать не следует. Если Dv(v’) было = 0, то теперь вершина v’ “разбалансирована”. Подобные вершины называются источниковыми и дописываются в конец D. Это нарушает порядок следования вершин в D, но, т.к. все источниковые вершины имеют ранг на 1 меньший, чем вершины, подвергнувшиеся балансировке, а они в свою очередь, после балансировки будут удалены из D, то элементы в D вновь станут упорядоченными по возрастанию рангов. При реализации метода, необходимо следить, чтобы балансировка продолжалась с вершины, которая была последней в D до начала балансировки, а не с добавляемых к D источниковых вершин. Также удобно ввести переменную, хранящую адрес 1-й источниковой вершины в D.

 

Достройка.

Достройка необходима в том случае, если g не является предпотоком или в D содержатся  источниковые вершины. Достройка производится последовательно в каждой вершине списка D, начиная с первой источниковой вершины до конца списка. Во время выполнения достройки в вершине, могут быть получены новые дефицитные вершины – они также дописываются в конец D и участвуют в достройке. Т.о. процедура достройки обрабатывает все источниковые и новые дефицитные вершины. При помещении в список новых дефицитных вершин, упорядоченность элементов по возрастанию рангов сохраняется.

Достройка в вершине. Пусть v – обрабатываемая вершина. Цель достройки – получение div(v) = 0, либо сделать ее блокированной. Для этого изменениются величины g(u) для u  A(v). Последовательно обрабатываем дуги u из A(v). Пусть u = (v, v’). Если A(v’) пуст, то вершина v’ блокирована => дуга u блокирована. В этом случае достройка в u не производится и u удаляется из A(v). Если же A(v’) не пуст, то не известно, блокирована дуга u или нет. Увеличим g(u) на y = min{ck(u) – g(u), -div(v)}. Внесем изменения и в остальные структуры: Dv(v) := Dv(v) + y, Dv(v’) := Dv(v’) – y. Добавим q(u) = y в список Q(v’). Если div(v) до изменения была = 0, то теперь она стала новой дефицитной вершиной и должна быть занесена в D, если div(v) была < 0, то она уже содержится в D.

Если после увеличения g(u) div(v) < 0, то g(u) = ck(u) – дуга u становится g-блокированной, удаляется из A(v) и процедура обрабатывает следующую дугу из списка. Если же div(v) = 0, то в вершине v установлен баланс – вершина удаляется из D, достройка в этой вершине прекращается.

Т.к.  при достройке предпотока в D заносятся только вершины, ранее ему не принадлежавшие, то рост списка D конечен.