Алгоритм Левита — различия между версиями
(→Алгоритм) |
(→Псевдокод) |
||
Строка 34: | Строка 34: | ||
<tex>M_2</tex>.add(u) | <tex>M_2</tex>.add(u) | ||
− | '''while''' <tex>M_1 \neq \varnothing</tex> ''':''' | + | '''while''' <tex>M_1^{'} \neq \varnothing</tex> '''and''' <tex>M_1^{''} \neq \varnothing</tex> ''':''' |
'''if''' <tex>M_1^{''} \neq \varnothing</tex> ''':''' | '''if''' <tex>M_1^{''} \neq \varnothing</tex> ''':''' | ||
u <tex>\gets</tex> <tex>M_1^{''}</tex>.pop() | u <tex>\gets</tex> <tex>M_1^{''}</tex>.pop() | ||
Строка 43: | Строка 43: | ||
'''if''' v <tex>\in M_2</tex> ''':''' | '''if''' v <tex>\in M_2</tex> ''':''' | ||
<tex>M_1^{'}</tex>.push(v) | <tex>M_1^{'}</tex>.push(v) | ||
− | relax(uv) | + | relax(uv, d) |
'''if''' v <tex>\in M_1</tex> ''':''' | '''if''' v <tex>\in M_1</tex> ''':''' | ||
− | relax(uv) | + | relax(uv, d) |
'''if''' v <tex>\in M_0</tex> '''and''' <tex>d_v > d_u + w_{uv}</tex> ''':''' | '''if''' v <tex>\in M_0</tex> '''and''' <tex>d_v > d_u + w_{uv}</tex> ''':''' | ||
<tex>M_1^{''}</tex>.push(v) | <tex>M_1^{''}</tex>.push(v) | ||
− | relax(uv) | + | relax(uv, d) |
<tex>M_0</tex>.add(u) | <tex>M_0</tex>.add(u) |
Версия 11:44, 30 ноября 2013
Алгоритм Левита (Levit algorithm) находит расстояние от заданной вершины
до всех остальных. Позволяет работать с ребрами отрицательного веса при отсутствии отрицательных циклов.Содержание
Алгоритм
Пусть
— текущая длина кратчайшего пути до вершины . Изначально, все элементы , кроме -го равны бесконечности; .Разделим вершины на три множества:
- — вершины, расстояние до которых уже вычислено (возможно, не окончательно)
- — вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на два упорядоченных подмножества:
- — основная очередь
- — срочная очередь
- — вершины, расстояние до которых еще не вычислено
Изначально все вершины, кроме
помещаются в множество . Вершина помещается в множество (в любую из очередей).
Шаг алгоритма: выбирается вершина из . Если очередь не пуста, то вершина берется из нее, иначе из . Далее, для каждого ребра :
- если , то переводится в конец очереди . При этом (производится релаксация ребра )
- если , то происходит релаксация ребра
- если и , то происходит релаксация ребра и помещается в
В конце шага помещаем вершину
в множество .
Алгоритм заканчивает работу, когда множество становится пустым.
Псевдокод
for uV : .add(s) for u s V : .add(u) while and : if : u .pop() else : u .pop() for uv E : if v : .push(v) relax(uv, d) if v : relax(uv, d) if v and : .push(v) relax(uv, d) .add(u)
Сложность
В худшем случае алгоритм Левита работает за
. Это происходит вследствие того, что некоторые вершины приходится обрабатывать повторно. Однако эксперементы показывают, что для реальных графов(например, карт дорог) данный алгоритм оказывается достаточно быстрым и эксперементальная оценка данного алгоритма составляет .См. также
Источники
- Алгоритм Левита - Википедия, свободная энциклопедия
- Алгоритм Левита - MAXimal::algo
- И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., стр. 228-234.