Алгоритм "поднять-в-начало" — различия между версиями
Whiplash (обсуждение | вклад) м (→Алгоритм) |
Whiplash (обсуждение | вклад) м |
||
| Строка 81: | Строка 81: | ||
{{Лемма | {{Лемма | ||
| + | |about = О применимости операции push | ||
|id = Лемма4 | |id = Лемма4 | ||
|statement = | |statement = | ||
| Строка 89: | Строка 90: | ||
{{Лемма | {{Лемма | ||
| + | |about = О применимости операции relabel | ||
|id = Лемма5 | |id = Лемма5 | ||
|statement = | |statement = | ||
| Строка 119: | Строка 121: | ||
<tex>nextVartex[u]</tex> возвращает вершину, следующую за <tex>u</tex> в списке <tex>L</tex>. Если <tex>u</tex> - последняя вершина в списке, то <tex>nextVartex[u] = null</tex>. | <tex>nextVartex[u]</tex> возвращает вершину, следующую за <tex>u</tex> в списке <tex>L</tex>. Если <tex>u</tex> - последняя вершина в списке, то <tex>nextVartex[u] = null</tex>. | ||
| + | |||
| + | == Корректность алгоритма == | ||
| + | Для доказательства корректности алгоритма, то есть чтобы показать что операция <tex>relabelToFront</tex> вычисляет поток, покажем, что она является реализацией универсального алгоритма [[Метод проталкивания предпотока|проталкивания предпотока]]. Для начала, заметим, что она выполняет операции <tex>push</tex> и <tex>relabel</tex> только тогда, когда они применимы, следует из лемм о применимости операций [[Алгоритм "поднять-в-начало"#Лемма4|push]] и [[Алгоритм "поднять-в-начало"#Лемма5|relabel]]. Покажем, что когда операция <tex>relabelToFront</tex> завершится, не применима ни одна основная операция. | ||
== Анализ == | == Анализ == | ||
Версия 13:02, 30 декабря 2012
Алгоритм "поднять-в-начало" (relabel-to-front) основан на методе проталкивание предпотока, но из-за тщательного выбора порядка выполнения операций проталкивания и подъема, время выполнения данного алгоритма составляет , что асимптотически не хуже, чем .
Содержание
Допустимые ребра
— сеть с истоком и стоком , — предпоток в , — функция высоты.
| Определение: |
| Допустимое ребро (admissible edge) — ребро , у которого и . В противном случае называется недопустимым (inadmissible). |
| Определение: |
| Допустимая сеть (admissible network) — сеть , где — множество допустимых ребер. |
| Лемма (Допустимая сеть является ациклической): |
Допустимая сеть является ациклической. |
| Доказательство: |
|
Пусть в существует циклический путь , где . для , так как каждое ребро данного пути допустимое. Просуммировав равенства вдоль циклического пути, получаем: Так как каждая вершина циклического пути встречается при суммировании по одному разу это значит то, что , что противоречит первоначальному предположению. Значит, допустимая сеть является ациклической. |
| Лемма (Об изменении допустимой цепи, с помощью операции проталкивания): |
Если вершина переполнена и ребро допустимое, то применяемая операция не создает новые допустимые ребра, но может привести к тому, что ребро станет недопустимым. |
| Доказательство: |
|
Так как ребро допустимое то, по определению допустимого ребра, из в можно протолкнуть поток. Из-за того что — переполнена, вызываем операцию . В результате выполнения операции может быть создано остаточное ребро . Так ребро допустимое то, , а это значит, что ребро не может стать допустимым. Если выполненная операция является насыщающим проталкиванием, то после ее выполнения и ребро становится недопустимым. |
| Лемма (Об изменении допустимой цепи, с помощью операции подъема): |
Если вершина переполнена и не имеется допустимых ребер, выходящих из , то применяется операция . После подъема появляется по крайней мере одно допустимое ребро, выходящее из , но нет допустимых ребер, входящих в . |
| Доказательство: |
|
Рассмотрим вершину . Если переполнена, то, согласно лемме (2), к ней может быть применима либо операция проталкивания, либо операция подъема. А так как не существует допустимых ребер для , то протолкнуть поток не возможно, значит, применяется операция . После данного подъема . Значит, если — вершина указанного множества, в которой реализуется минимум, то становится допустимым. А это значит, что после подъема существует хотя бы одно допустимое ребро, выходящее из . Пусть существует такая вершина , после подъема, что ребро допустимо. Тогда , значит, перед подъемом . Но между вершинами, высоты которых отличаются более чем на 1, не существует остаточных сетей. Кроме того, подъем вершины не меняет остаточную сеть. Значит, ребро не может находится в допустимой сети, так как оно не принадлежит остаточной сети. |
Идея
Операция разгрузки (discharge)
Разгрузка (discharge) — операция, которая применяется к переполненной вершине , для того чтобы протолкнуть поток через допустимые ребра в смежные вершины, при необходимости поднимая , делая недопустимые ребра, выходящие из вершины , допустимыми.
Будем хранить для каждой вершины список (список вершин смежных с ней). То есть список содержит каждую вершину такую, что в сети или .
На первую вершину в списке указывает указатель . Для перехода к следующей вершине в списке за , поддерживается указатель . Он равен , если — последняя вершина в списке.
Для каждой вершины указатель — указатель на текущую вершину списка. Изначально .
discharge(u)
while e[u] > 0
v = current[u]
if v = null
relabel(u)
current[u] = head[N[u]]
else
if c(u, v) - f(u, v) > 0 and h[u] = h[v] + 1
push(u, v)
else
current[u] = next[v]
Операция завершится только тогда, когда избыток станет равным нулю, и ни подъем, ни перемещение указателя не влияет на значение .
Докажем то, что когда операция discharge вызывает операции push и relable, эти операции применимы.
| Лемма (О применимости операции push): |
Когда операция вызывает в операцию , то для пары вершин применима операция проталкивания. |
| Доказательство: |
| Проверки операции , сделанные до вызова операции проталкивания, гарантируют то, что операция будет вызвана только тогда, когда она применима. То есть , и . |
| Лемма (О применимости операции relabel): |
Когда операция вызывает в операцию , то для вершины применим подъем. |
| Доказательство: |
|
Из леммы об изменении допустимой цепи (для операции relabel) и условия следует, что для доказательства данной леммы необходимо показать, что все ребра выходящие из , являются недопустимыми. Каждый проход операции начинается с головы списка и оканчивается, когда . Именно тогда вызывается и начинается новый проход. К концу прохода все ребра, выходящие из , станут недопустимыми. Так как из леммы об изменении допустимой цепи (для операции push) следует, что операции проталкивания не создают допустимых ребер. То есть любое допустимое ребро могло быть создано только в результате выполнения операции подъема. Но вершина не подвергается подъему во время прохода, а любая другая вершина , для которой вызывалась операция подъема, во время данного прохода, не имеет после подъема допустимых ребер, что следует из леммы об изменении допустимой цепи (для операции relabel). Значит, в конце прохода все ребра, выходящие из , останутся недопустимыми. |
Алгоритм
Инициализируем предпоток и высоты, с помощью операции initializePreflow, список - список для хранения всех вершин графа, кроме стока и истока. Проинициализируем указатель каждой вершины , чтобы он указывал на первую вершину в списке .
Пройдем по списку разгружая вершины, начиная с первой вершины. И если операция изменила высоту вершины, то перемещаем ее в начало списка . Передвинем указатель на следующую вершину списке , если после разгрузки была изменена высота, то берем следующую вершину в новом списке .
relabelToFront(s, t)
initializePreflow(s)
L = V / {s, t}
for u V / {s, t}
current[u] = head[N[u]]
u = head[L]
while u != null
oldHeight = h[u]
discharge(u)
if h[u] > oldHeight
передвинуть u в начало списка L
u = nextVartex[u]
В приведенном псевдокоде предполагается, что для каждой вершины уже создан список .
возвращает вершину, следующую за в списке . Если - последняя вершина в списке, то .
Корректность алгоритма
Для доказательства корректности алгоритма, то есть чтобы показать что операция вычисляет поток, покажем, что она является реализацией универсального алгоритма проталкивания предпотока. Для начала, заметим, что она выполняет операции и только тогда, когда они применимы, следует из лемм о применимости операций push и relabel. Покажем, что когда операция завершится, не применима ни одна основная операция.
Анализ
Источники
- Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. — 2-е изд. — М.: Издательский дом «Вильямс», 2011. — С. 774—785.
- Алгоритм проталкивания предпотока — Википедия