- •Элементарные алгоритмы для работы с графами
- •Работа алгоритма[править | править вики-текст]
- •Неформальное описание[править | править вики-текст]
- •Формальное описание[править | править вики-текст]
- •Алгоритм поиска в глубину[править | править вики-текст]
- •Нерекурсивные варианты[править | править вики-текст]
- •Общая идея
- •[Править]Пошаговое представление
- •[Править]Реализация
- •[Править]Время работы
- •[Править]Цвета вершин
- •Топологическая сортировка и сильно связные компоненты
- •↑ Пример ориентированного неотсортированного графа, к которому применима топологическая сортировка
- •Пример работы алгоритма[править | править вики-текст]
- •Алгоритмы[править | править вики-текст]
- •Минимальные остовные деревья (мst)
- •Введение
- •Постановка задачи
- •Кратчайшие пути
- •Давайте придумаем что-нибудь простое
- •А если я педант?
- •Задача о максимальном потоке
- •[Править]Определение потока
- •[Править]Пример
- •Увеличивающие пути. Теорема Бержа
- •Алгоритм Эдмондса. Сжатие цветков
- •Эффективная реализация
- •Оптимизация: предварительное построение паросочетания
- •Случай двудольного графа
- •Дальнейшая оптимизация
- •[Править]Реализация
- •[Править]Оценка производительности
- •[Править]Пример несходящегося алгоритма
- •[Править]Оценка быстродействия
- •[Править]Литература
- •Максимальные паросочетания[править | править вики-текст]
- •Описание алгоритма Необходимые определения
- •Теорема Бержа
- •Алгоритм Куна
- •Время работы
- •Реализация
- •Улучшенная реализация
- •[Править]Постановка задачи
- •[Править]Решение
- •[Править]Псевдокод
- •Префиксы и суффиксы строки
- •Прямые переходы
- •[Править]Суффиксные ссылки
- •Основные определения и описание структуры[править | править вики-текст]
- •Свойства суффиксных деревьев[править | править вики-текст]
- •Требования суффиксного дерева к памяти[править | править вики-текст]
- •[Править]Недостатки
- •Метод хеширования
- •[Править]Алгоритм
- •[Править]Псевдокод
- •[Править]Время работы
- •[Править]Надёжность
- •Автоматные модели в программировании
- •[Править]Переходы между состояниями [править]Прямые переходы
- •[Править]Суффиксные ссылки
- •[Править]Псевдокод
- •[Править]Пример использования
- •[Править]Псевдокод
- •[Править]Пример
- •[Править]Время работы
- •[Править]Эффективный алгоритм
- •[Править]Псевдокод
- •[Править]Время работы
- •[Править]Построение префикс-функции по z-функции [править]Постановка задачи
- •[Править]Описание алгоритма
- •Приближенные алгоритмы решения np-трудных задач
Оптимизация: предварительное построение паросочетания
Как и в случае Алгоритма Куна, перед выполнением алгоритма Эдмондса можно каким-нибудь простым алгоритмом построить предварительное паросочетание. Например, таким жадным алгоритмом:
for (int i=0; i<n; ++i)
if (match[i] == -1)
for (size_t j=0; j<g[i].size(); ++j)
if (match[g[i][j]] == -1) {
match[g[i][j]] = i;
match[i] = g[i][j];
break;
}
Такая оптимизация значительно (до нескольких раз) ускорит работу алгоритма на случайных графах.
Случай двудольного графа
В
двудольных графах отсутствуют циклы
нечётной длины, и, следовательно, код,
выполняющий сжатие цветков, никогда не
выполнится. Удалив мысленно все части
кода, обрабатывающие сжатие цветков,
мы получим Алгоритм
Куна практически
в чистом виде. Таким образом, на двудольных
графах алгоритм Эдмондса вырождается
в алгоритм
Куна и
работает за
.
Дальнейшая оптимизация
Во всех вышеописанных операциях с цветками легко угадываются операции с непересекающимися множествами, которые можно выполнять намного эффективнее (см. Система непересекающихся множеств). Если переписать алгоритм с использованием этой структуры, то асимптотика алгоритма понизится до . Таким образом, для произвольных графов мы получили ту же асимптотическую оценку, что и в случае двудольных графов (алгоритм Куна), но заметно более сложным алгоритмом.
Метод Форда-Фалкерсона (верхняя оценка на время работы; пример, на котором она достигается)
Теорема: |
Если — некоторый поток в сети с источником и стоком , то следующие утверждения эквивалентны:
|
Доказательство: |
|
Докажем
от противного. Предположим, что
в
существует
какой-нибудь путь
Рассмотрим
множество
Так
как существует разрез, такой что
,
то согласно следствию
леммы о слабой двойственности потока
и разреза |
|
Идея
Идея
алгоритма заключается в следующем.
Изначально величине потока присваивается
значение 0:
для
всех
из
.
Затем величина потока итеративно
увеличивается посредством поиска
увеличивающего пути (путь от источника
s к стоку t, вдоль которого можно послать
ненулевой поток). В данной статье
рассматривается алгоритм, осуществляющий
этот поиск с помощью обхода
в глубину (dfs).
Процесс повторяется, пока можно найти
увеличивающий путь.
[Править]Реализация
dfs(u, Cmin) {
if (u = t)
return Cmin
u.vis <- true
for (uv in E)
if (!v.vis) && (uv.f < uv.c)
дельта <- dfs(v, min(Cmin, uv.c - uv.f))
if (дельта > 0) {
uv.f += дельта
uv.backEdge.f -= дельта
return дельта
}
return 0
}
