Алгоритм Левита — различия между версиями
(→Доказательство) |
Lehanyich (обсуждение | вклад) |
||
Строка 1: | Строка 1: | ||
− | '''Алгоритм Левита''' (Levit algorithm) находит расстояние от заданной вершины <tex>s</tex> до всех остальных. Позволяет работать с ребрами отрицательного веса при отсутствии отрицательных циклов. | + | '''Алгоритм Левита''' (англ. ''Levit's algorithm'') находит расстояние от заданной вершины <tex>s</tex> до всех остальных. Позволяет работать с ребрами отрицательного веса при отсутствии отрицательных циклов. |
== Алгоритм == | == Алгоритм == | ||
Строка 26: | Строка 26: | ||
== Псевдокод == | == Псевдокод == | ||
− | '''for''' u <tex>\in</tex> | + | '''for''' u : u <tex>\in V</tex> |
− | <tex> | + | d[v] <tex>\leftarrow \infty</tex> |
− | <tex> | + | d[s] <tex>\leftarrow 0</tex> |
− | + | <tex>M_1^{'}</tex>.push(s) | |
− | <tex>M_1^{ | + | '''for''' u : u <tex>\neq</tex> s '''and''' uv <tex>\in V</tex> |
− | '''for''' u <tex>\neq</tex> s <tex>\in</tex> | + | <tex>M_2</tex>.push(u) |
− | <tex>M_2</tex>. | + | '''while''' <tex>M_1^{'} \neq \varnothing</tex> '''and''' <tex>M_1^{''} \neq \varnothing</tex> |
− | + | '''if''' <tex>M_1^{''} \neq \varnothing</tex> | |
− | '''while''' <tex>M_1^{'} \neq \varnothing</tex> '''and''' <tex>M_1^{''} \neq \varnothing</tex> | + | '''int''' u <tex>=</tex> <tex>M_1^{''}</tex>.pop() |
− | '''if''' <tex>M_1^{''} \neq \varnothing</tex> ''' | ||
− | |||
'''else :''' | '''else :''' | ||
− | u <tex> | + | '''int''' u <tex>=</tex> <tex>M_1{'}</tex>.pop() |
− | + | '''for''' v : uv <tex>\in E</tex> | |
− | '''for''' uv <tex>\in</tex> | + | '''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) | ||
<tex>M_2</tex>.remove(v) | <tex>M_2</tex>.remove(v) | ||
− | + | d[v] <tex>=</tex> min(d[v], d[u] <tex>+</tex> <tex>w_{uv}</tex>) | |
− | '''if''' v <tex>\in M_1</tex> | + | '''if''' v <tex>\in M_1</tex> |
− | + | d[v] = min(d[v], d[u] + <tex>w_{uv}</tex>) | |
− | '''if''' v <tex>\in M_0</tex> '''and''' <tex> | + | '''if''' v <tex>\in M_0</tex> '''and''' d[v] <tex>></tex> d[u] <tex>+</tex> <tex>w_{uv}</tex> |
<tex>M_1^{''}</tex>.push(v) | <tex>M_1^{''}</tex>.push(v) | ||
<tex>M_0</tex>.remove(v) | <tex>M_0</tex>.remove(v) | ||
− | + | d[v] <tex>=</tex> d[u] <tex>+</tex> <tex>w_{uv}</tex> | |
− | + | <tex>M_0</tex>.push(u) | |
− | <tex>M_0</tex>. | ||
== Доказательство == | == Доказательство == | ||
Строка 75: | Строка 71: | ||
== Сложность == | == Сложность == | ||
− | В худшем случае алгоритм Левита работает за экспоненциальное время. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим хуже алгоритма [[Алгоритм Дейкстры|Дейкстры]]. | + | В худшем случае алгоритм Левита работает за экспоненциальное время. Достаточно рассмотреть полный граф <tex>K_n</tex> с достаточно большим n и такими весами, что: <tex>w_{uv} = 0</tex>, если <tex>u \neq 1</tex> и <tex>w_{uv} = n - v + 2</tex>, если <tex>u = 1</tex>.Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим хуже алгоритма [[Алгоритм Дейкстры|Дейкстры]]. |
== Источники == | == Источники == | ||
− | * [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Алгоритм Левита - Википедия | + | * [http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D0%B5%D0%B2%D0%B8%D1%82%D0%B0 Алгоритм Левита - Википедия] |
− | * [http://e-maxx.ru/algo/levit_algorithm Алгоритм Левита | + | * [http://e-maxx.ru/algo/levit_algorithm Алгоритм Левита] |
− | * И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., стр. | + | * И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231. |
+ | |||
+ | [[Категория: Алгоритмы и структуры данных]] | ||
+ | [[Категория: Кратчайшие пути в графах]] |
Версия 22:51, 5 ноября 2015
Алгоритм Левита (англ. Levit's algorithm) находит расстояние от заданной вершины
до всех остальных. Позволяет работать с ребрами отрицательного веса при отсутствии отрицательных циклов.Содержание
Алгоритм
Пусть
— текущая длина кратчайшего пути до вершины . Изначально, все элементы , кроме -го равны бесконечности; .Разделим вершины на три множества:
- — вершины, расстояние до которых уже вычислено (возможно, не окончательно)
- — вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две очереди:
- — основная очередь
- — срочная очередь
- — вершины, расстояние до которых еще не вычислено
Изначально все вершины, кроме
помещаются в множество . Вершина помещается в множество (в любую из очередей).
Шаг алгоритма: выбирается вершина из . Если очередь не пуста, то вершина берется из нее, иначе из . Далее, для каждого ребра :
- если , то переводится в конец очереди . При этом (производится релаксация ребра )
- если , то происходит релаксация ребра
- если и , то происходит релаксация ребра и помещается в
В конце шага помещаем вершину
в множество .
Алгоритм заканчивает работу, когда множество становится пустым.
Псевдокод
for u : ud[v] d[s] .push(s) for u : u s and uv .push(u) while and if int u .pop() else : int u .pop() for v : uv if v .push(v) .remove(v) d[v] min(d[v], d[u] ) if v d[v] = min(d[v], d[u] + ) if v and d[v] d[u] .push(v) .remove(v) d[v] d[u] .push(u)
Доказательство
Лемма: |
Алгоритм отработает за конечное время |
Доказательство: |
Не теряя общности, будем считать, что граф связен. Тогда алгоритм завершит работу, когда в | окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из в тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в . Тогда за конечное число шагов все вершины окажутся в .
Лемма: |
В конце работы алгоритма не найдется такое ребро , что его релаксация будет успешной |
Доказательство: |
Предположим обратное. Тогда рассмотрим 2 случая:
|
Из двух предыдущих лемм напрямую следует корректность алгоритма.
Сложность
В худшем случае алгоритм Левита работает за экспоненциальное время. Достаточно рассмотреть полный граф Форда Беллмана и не многим хуже алгоритма Дейкстры.
с достаточно большим n и такими весами, что: , если и , если .Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритмИсточники
- Алгоритм Левита - Википедия
- Алгоритм Левита
- И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.