Алгоритм Левита
Алгоритм Левита (англ. Levit's algorithm) находит расстояние от заданной вершины до всех остальных. Позволяет работать с ребрами отрицательного веса при отсутствии отрицательных циклов.
Алгоритм
Пусть — текущая длина кратчайшего пути до вершины . Изначально, все элементы , кроме -го равны бесконечности; .
Разделим вершины на три множества:
- — вершины, расстояние до которых уже вычислено (возможно, не окончательно),
- — вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две очереди:
- — основная очередь,
- — срочная очередь;
- — вершины, расстояние до которых еще не вычислено.
Изначально все вершины, кроме помещаются в множество . Вершина помещается в множество (в любую из очередей).
Шаг алгоритма: выбирается вершина из . Если очередь не пуста, то вершина берется из нее, иначе из . Для каждого ребра возможны три случая:
- , то переводится в конец очереди . При этом (производится релаксация ребра ),
- , то происходит релаксация ребра ,
- и , то происходит релаксация ребра и помещается в .
В конце шага помещаем вершину в множество .
Алгоритм заканчивает работу, когда множество становится пустым.
Псевдокод
for .push() for and .push() while and int if .pop() else .pop() for if .push() .remove() min() else if v min() else if and .push() .remove() .push()
Доказательство
| Лемма: |
Алгоритм отработает за конечное время |
| Доказательство: |
| Не теряя общности, будем считать, что граф связен. Тогда алгоритм завершит работу, когда в окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из в тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в . Тогда за конечное число шагов все вершины окажутся в . |
| Лемма: |
В конце работы алгоритма не найдется такое ребро , что его релаксация будет успешной |
| Доказательство: |
|
Предположим обратное. Тогда рассмотрим 2 случая:
|
Из двух предыдущих лемм напрямую следует корректность алгоритма.
Сложность
В плохих случаях алгоритм Левита работает очень долго. Например, в полном графе с достаточно большим и весами , рёбра идут в лексикографическом порядке. Добавление вершины в очередь и последующая её обработка влекут добавление из в всех её предыдущих вершин, начиная со -ой; дойдя до вершины , в снова добавятся вершины меньше (кроме первой). Таким образом, вершину добавят в раз, всего в будет добавлений. В очень плохих случаях вершина может помещаться в очередь до раз, что даёт экспоненциальное время. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм Форда Беллмана и не многим уступает алгоритму Дейкстры.
См. также
- Алгоритм A*
- Алгоритм Дейкстры
- Алгоритм Джонсона
- Алгоритм Флойда
- Алгоритм Форда-Беллмана
- Обход в ширину
Источники
- Википедия — Алгоритм Левита
- e-maxx — Алгоритм Левита
- И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.