|
Кружок обучения мастерству программирования при СПбГУ |
Лекции группы A0 - Лекция 07 - Семинар по Preflow-Push (Юра Землянский, Коля Мальковский)
Note: Звездочкой отмечены темы, на которые на лекции времени не хватило.
Краткий план лекции на тему "Семинар по Preflow-Push"
- Определения
- Основные Леммы (вытекают из инварианта), основные Операции
- Оценки на количества элементарных операций
- Алгоритмы PreflowPush и MoveToFront
- Оптимизации [High-Level, Global Relabeling, P2R, Two Phase]
- СНМ и его использование
- Offline методы в геометрии
Полный план лекции
- Определения
- предпоток, избыток e[v], активная вершина
- проталкивание (насыщенное, ненасыщенное)
- высотная функция, инвариант h[v] <= h[w] + 1 для ненасыщенного ребра v --> w
- Основные Леммы (вытекают из инварианта), основные Операции
- Из s нет дополняющего пути в t.
- Операция Push по ребрам вида h[v] = h[w] + 1 (насыщенный, ненасыщенный)
- Операция ReLabel (подъем)
- Операция DisCharge (e[v] > 0 => Push down... iff can not ReLabel)
- e[v] > 0 => существует путь в исток
- Высоты вершин не более 2n-1 (т.к. вершина поднимается только если e[v] > 0, а тогда сущ путь в исток)
- Алгоритм сойдется к потоку (т.е. придет в состояние, когда e[v] = 0, для обычной v)
- Полученный поток максимальный (т.к. не существует дополняющего пути из s в t)
- Оценки на количества элементарных операций
- Операций ReLabel O(V^2) (h[v] <= 2n-1)
- Насыщенных операций Push O(VE) (высота растет)
- Ненасыщенных операций ReLabel O(V^2*E) (для доказательства этого факта вводим функцию-потенциал = сумма высот)
- DisCharge : (вызывается только, если e[v] > 0)
cnt = 0
while e[v] > 0 and cnt < deg[v] do
Push(curE), curE = next, cnt++
if e[v] > 0
ReLabel
- Все DisCharge-ы в сумме работают за O(VE) + O(число_вызовов)
(между подъемами вершины v каждое ребро насыщается максимум 1 раз
- Алгоритмы PreflowPush и MoveToFront
- Инитиализация предпотока : h[s] = n, h[v != s] = 0, все ребра исходящие из s насыщены.
- PreflowPush :
while run
for v : e[v] > 0
DisCharge(v)
- PreflowPush работает за O(V^2*E) = max из количеств всевозможных операций
- MoveToFront :
while run
for v in List (пробегаем список целиком)
if e[v] > 0
DisCharge(v)
if e[v] > 0
MoveToFront(v) (поместить вершину v в начало списка)
- MoveToFront работает за O(V^3)
Инвариант списка : ненасыщенные ребра идут вперед
Поддерживается т.к. если вершина переместилась=поднялась, то в нее не могут входить ненасыщенные ребра.
Инвариант списка => если мы дошли до конца списка без подъемов, то поток найден.
=> внутри каждой фазы цикла "while run" происходит хотя бы 1 ReLabel, а их O(V^2) => O(V^3)
- Оптимизации
- High-Level
Поддерживаем List[h] - список вершин с избытком (активных) фиксированной высоты.
Выбираем каждый раз v : e[v] > 0, h[v] = max, делаем DisCharge(v)
Для этого поддерживаем maxH, и изменяем ее (Если список опустел dec, пока нужно. Если появилась более высокая, inc.)
Sum (dec) <= Sum (inc) = O(n^2)
- Global Relabeling
h[v] <= d[v,t] (расстояние от v до стока)
За O(E) (1 bfs) можем сделать h[v] := d[v,t] (при этом высоты вершин увеличиваются)
Этот bfs следует делать каждые C*E операций.
- Про дырки в высотной функции
Если h[v] >= n, то весь ее избыток пойдет обратно в s
Дырка в высотной фугкции ВСЕГДА ровно 1. Она как раз разделяет вершины h[v] >= n и h[v] < n.
Если нас интересует только величина потока, можно вершины h[v] >= n выкидывать из графа.
Если сделать 2Phase алгоритм сперва (h[v] < n) --> t, потом (h[v] >= n) --> s, будет быстрее.
- P2R (Push 2 Level Relabeling)
[v --> u] не (c[e] - f[e]), а min(c[e] - f[e], rest[u]) (rest[u] - сколько мы можем из u толкнуть вниз)
И если (c[e] - f[e] > rest[u]) сразу поднять вершину u.
- СНМ и его использование
- Offline задача про минимумы на пути в дереве с O(n + m) памяти и O(mlogn) времени
- Доказательство амортизационной оценки O(mlogn) на сжатие путей в СНМ
- Offline методы в геометрии
- K точек. Определить, где они находятся, относительно невыпуклого N-угольника (INSIDE, OUTSIDE, BORDER) за O(NlogN + KlogK) [ScanLine]
- В случае выпуклого O(N + KlogK)
- Поиск экстремальных точек для K прямых и выпуклого N-угольника за O(N + KlogK) [2 указателя]
- Проверка для множества точек, разделяют ли их прямые = построить выпуклую оболочку и (см. выше)