← Все вопросы

Почему наивный Форд-Фалкерсон с DFS может работать очень долго или не завершиться?

Задан 9 месяцев назад848 просмотров2 ответа
10

Написал Форд-Фалкерсон: ищу любой увеличивающий путь обычным DFS и пускаю поток. На одном тесте программа работает подозрительно долго, хотя граф маленький (всего 4 вершины, но большие пропускные). Почему так и как это лечить?

2 ответа

16
✓ Принятый ответ — помог автору

Проблема в том, что наивный DFS может выбирать плохие увеличивающие пути, пуская по 1 единице за раз, хотя пропускные огромные.

Классический «злой» тест. Граф: s,a,b,ts, a, b, t. Рёбра:

s->a : 10^9
s->b : 10^9
a->b : 1        (узкая «диагональ»)
a->t : 10^9
b->t : 10^9

Если DFS каждый раз ходит через диагональ aba\to b (то туда, то обратно по обратному ребру), он пускает по 1 единице за итерацию и делает порядка 21092\cdot 10^9 итераций. Каждая итерация — O(E)O(E), итого катастрофа, хотя ответ (21092\cdot 10^9) находится за 2 «умных» пути.

Асимптотика наивного FF: O(Eflow)O(E \cdot \text{flow}) — зависит от величины потока, а не только от размера графа. При больших пропускных flow огромен → TLE. На иррациональных capacity алгоритм теоретически даже не завершается.

Лечение (любое из):

  1. Эдмондс-Карп — брать кратчайший путь через BFS. O(VE2)O(VE^2), не зависит от величины потока.
  2. Диниц — слоистая сеть + блокирующий поток. O(V2E)O(V^2E), на практике быстрее всех.
  3. Capacity scaling — пускать сначала по толстым рёбрам. O(E2logU)O(E^2\log U).

На олимпиаде по умолчанию пишите Диница — он обходит эту патологию и быстр на реальных тестах.

6

Добавлю про коварность: на случайных или «дружелюбных» тестах наивный FF с DFS часто проходит, потому что плохих путей не возникает. Поэтому баг легко не заметить локально, а на максимальном/специально подобранном тесте словить TLE. Никогда не сдавайте наивный FF в задачах, где пропускные могут быть большими (> нескольких тысяч). Если граф с единичными пропускными (паросочетания, Менгер) — наивный FF фактически вырождается в Куна и работает O(VE)O(VE), там это допустимо. Но привычку лучше выработать сразу: max-flow = Диниц.

Ваш ответ

Войдите, чтобы ответить на вопрос.