Алгоритм "поднять-в-начало" — различия между версиями
(→Операция разгрузки (discharge)) |
(→Алгоритм) |
||
| Строка 103: | Строка 103: | ||
Инициализируем предпоток и высоты, с помощью операции [[Метод проталкивания предпотока#Схема алгоритма|<tex>\mathtt{initializePreflow}</tex>]]. Список <tex>L</tex> {{---}} список для хранения всех вершин графа, кроме стока и истока. Проинициализируем указатель <tex>current</tex> каждой вершины <tex>u</tex>, чтобы он указывал на первую вершину в списке <tex>u</tex>. | Инициализируем предпоток и высоты, с помощью операции [[Метод проталкивания предпотока#Схема алгоритма|<tex>\mathtt{initializePreflow}</tex>]]. Список <tex>L</tex> {{---}} список для хранения всех вершин графа, кроме стока и истока. Проинициализируем указатель <tex>current</tex> каждой вершины <tex>u</tex>, чтобы он указывал на первую вершину в списке <tex>u</tex>. | ||
| − | Пройдем по списку <tex>L</tex>, разгружая вершины, начиная с первой. И если операция <tex>discharge</tex> изменила высоту вершины, то перемещаем ее в начало списка <tex>L</tex>. Передвинем указатель на следующую вершину списке <tex>L</tex>. Если после разгрузки была изменена высота, то берем следующую вершину в новом списке <tex>L</tex>. | + | Пройдем по списку <tex>L</tex>, разгружая вершины, начиная с первой. И если операция <tex>\mathtt{discharge}</tex> изменила высоту вершины, то перемещаем ее в начало списка <tex>L</tex>. Передвинем указатель на следующую вершину списке <tex>L</tex>. Если после разгрузки была изменена высота, то берем следующую вершину в новом списке <tex>L</tex>. |
'''function''' <tex>\mathtt{relabelToFront}(s, t): </tex>''' | '''function''' <tex>\mathtt{relabelToFront}(s, t): </tex>''' | ||
Версия 23:01, 4 января 2016
Алгоритм "поднять-в-начало" (англ. relabel-to-front) основан на методе проталкивание предпотока, но из-за тщательного выбора порядка выполнения операций проталкивания и подъема, время выполнения данного алгоритма составляет , что асимптотически не хуже, чем .
Содержание
Допустимые ребра
— сеть с истоком и стоком , — предпоток в , — функция высоты.
| Определение: |
| Допустимое ребро (англ. admissible edge) — ребро , у которого и . В противном случае называется недопустимым (англ. inadmissible). |
| Определение: |
| Допустимая сеть (англ. admissible network) — сеть , где — множество допустимых ребер. |
| Лемма (Допустимая сеть является ациклической): |
Допустимая сеть является ациклической. |
| Доказательство: |
|
Пусть в существует циклический путь , где . для , так как каждое ребро данного пути допустимое. Просуммировав равенства вдоль циклического пути, получаем: Вершина циклического пути встречается при суммировании по одному разу. Значит, , что противоречит первоначальному предположению. Следовательно, допустимая сеть является ациклической. |
| Лемма (Об изменении допустимой цепи с помощью операции проталкивания): |
Если вершина переполнена и ребро допустимое, то применяемая операция не создает новые допустимые ребра, но может привести к тому, что ребро станет недопустимым. |
| Доказательство: |
|
Из в можно протолкнуть поток, так как ребро допустимое, по определению. Из-за того что — переполнена, вызываем операцию . В результате выполнения операции может быть создано остаточное ребро . Поскольку ребро допустимое, то , а это значит, что ребро не может стать допустимым. Если выполненная операция является насыщающим проталкиванием, то после ее выполнения и ребро становится недопустимым. |
| Лемма (Об изменении допустимой цепи с помощью операции подъема): |
Если вершина переполнена и не имеется допустимых ребер, выходящих из , то применяется операция . После подъема появляется по крайней мере одно допустимое ребро, выходящее из , но нет допустимых ребер, входящих в . |
| Доказательство: |
|
Рассмотрим вершину . Если переполнена, то, согласно лемме (2), к ней может быть применима либо операция проталкивания, либо операция подъема. А так как не существует допустимых ребер для , то протолкнуть поток не возможно, значит, применяется операция . После данного подъема . Значит, если — вершина указанного множества, в которой реализуется минимум, то становится допустимым. А это значит, что после подъема существует, хотя бы одно, допустимое ребро, выходящее из . Пусть, после подъема существует такая вершина , что ребро допустимо. Тогда после подъема , а перед ним . Но между вершинами, высоты которых отличаются более чем на 1, не существует остаточных ребер. Кроме того, подъем вершины не меняет остаточную сеть. Значит, ребро не может находится в допустимой сети, так как оно не принадлежит остаточной сети. |
Операция разгрузки (discharge)
Разгрузка (англ. discharge) — операция, применяемая к переполненной вершине , для того чтобы протолкнуть поток через допустимые ребра в смежные вершины, при необходимости поднимая , делая недопустимые ребра, выходящие из вершины , допустимыми.
Будем хранить для каждой вершины список (список вершин, смежных с ней). То есть список содержит каждую вершину такую, что в сети или .
На первую вершину в списке указывает указатель . Для перехода к следующей вершине в списке за , поддерживается указатель . Он равен , если — последняя вершина в списке.
Для каждой вершины указатель — указатель на текущую вершину списка. Изначально .
function while if else if else
Операция завершится только тогда, когда избыток станет равным нулю, и ни подъем, ни перемещение указателя не влияет на значение .
Докажем, что когда вызывает операции push и relable, они применимы.
| Лемма (О применимости операции push): |
Когда вызывает в операцию , то для пары вершин применима операция проталкивания. |
| Доказательство: |
| Проверки операции , сделанные до вызова операции проталкивания, гарантируют то, что операция будет вызвана только тогда, когда она применима. То есть , и . |
| Лемма (О применимости операции relabel): |
Когда вызывает в операцию , то для вершины применим подъем. |
| Доказательство: |
|
Из леммы об изменении допустимой цепи (для операции relabel) и условия следует, что для доказательства данной леммы необходимо показать, что все ребра, выходящие из , являются недопустимыми. Каждый проход операции начинается с головы списка и оканчивается, когда . Именно тогда вызывается , и начинается новый проход. К концу прохода все ребра, выходящие из , станут недопустимыми, так как из леммы об изменении допустимой цепи (для операции push) следует, что операции проталкивания не создают допустимых ребер. То есть любое допустимое ребро могло быть создано только в результате выполнения операции подъема. Но вершина не подвергается подъему во время прохода, а любая другая вершина , для которой вызывалась операция подъема, во время данного прохода, не имеет после подъема допустимых ребер, что следует из леммы об изменении допустимой цепи (для операции relabel). Значит, в конце прохода все ребра, выходящие из , останутся недопустимыми. |
Алгоритм
Инициализируем предпоток и высоты, с помощью операции . Список — список для хранения всех вершин графа, кроме стока и истока. Проинициализируем указатель каждой вершины , чтобы он указывал на первую вершину в списке .
Пройдем по списку , разгружая вершины, начиная с первой. И если операция изменила высоту вершины, то перемещаем ее в начало списка . Передвинем указатель на следующую вершину списке . Если после разгрузки была изменена высота, то берем следующую вершину в новом списке .
function for while if передвинуть в начало списка
В приведенном псевдокоде предполагается, что для каждой вершины уже создан список .
хранит вершину, следующую за в списке . Если — последняя вершина в списке, то .
Инвариант цикла: "при каждом выполнении условия вхождения в цикл while вершины в списке топологически упорядочены в допустимой сети , и ни одна вершина, стоящая в списке перед , не имеет избыточного потока".
Корректность алгоритма
Для доказательства корректности алгоритма, то есть чтобы показать что операция вычисляет поток, покажем, что она является реализацией универсального алгоритма проталкивания предпотока. Для начала, заметим, что она выполняет операции и только тогда, когда они применимы, следует из лемм о применимости операций push и relabel. Покажем, что когда операция завершится, не применима ни одна основная операция. Для этого подробно рассмотрим операцию :
- После вызова и для всех . Так как , то ни одно ребро не является допустимым. Значит, и любой порядок множества является топологическим упорядочением .
- Проверим, что топологическое упорядочение сохранится при проведении итераций цикла while. Для начала заметим, что сеть может изменится только из-за операций проталкивания и подъема. Из леммы об изменении допустимой цепи нам известно, что после операции проталкивания новые допустимые ребра не появляются, а это значит, что они могли появится только во время выполнения операции подъема. После того как для вершины применили операцию подъема, больше не существует допустимых ребер, входящих в , но могут быть допустимые ребра, выходящие из нее. Таким образом, перемещая в начало списка , все допустимые ребра, выходящие из , удовлетворяют условию топологического упорядочения.
- Проверим, что ни одна вершина, предшествующая в списке , не имеет избытка потока. Пусть вершина — вершина на следующей итерации.
- Если подверглась подъему, то вершин предшествующих на следующей итерации, кроме , нет или если высота не изменилась, то там остались те же вершины, что и ранее. Так как подверглась разгрузке, то она не содержит избытка потока. Значит, если подверглась подъему в процессе разгрузки, то ни одна вершина, предшествующая , не содержит избытка потока.
- Если высота не поменялась во время разгрузки, то вершины, стоящие в списке перед ней, не получили избыток потока, так как топологически упорядочен все время в процессе разгрузки, поэтому каждая операция проталкивания продвигает поток только по вершинам дальше по списку. В этом случае ни одна вершина, предшествующая , также не имеет избытка потока.
- После завершения цикла , поэтому избыток всех вершин равен (инвариант цикла). Значит, ни одна основная операция неприменима.
Оценка быстродействия
| Теорема: |
Время выполнения операции для любой сети составляет . |
| Доказательство: |
|
Пусть фаза — время между двумя последовательными операциями подъема. Так как всего, по лемме (6), выполняется подъемов, значит, в алгоритме всего фаз. Если операция не выполняет подъем, то следующий ее вызов происходит дальше по списку длина меньше . Если же подъем выполняется, то следующий вызов происходит уже в другой фазе алгоритма. Значит, каждая фаза содержит не более вызовов . Таким образом, цикл while процедуры выполняет работу (без учета операций вызываемых в ), за . Оценим работу выполнения внутри операции :
|
Источники Информации
- Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. — 2-е изд. — М.: Издательский дом «Вильямс», 2011. — С. 774—785.
- Алгоритм проталкивания предпотока — Википедия