Алгоритм Левита — различия между версиями
Lehanyich (обсуждение | вклад) (→Псевдокод) |
Lehanyich (обсуждение | вклад) |
||
Строка 13: | Строка 13: | ||
Изначально все вершины, кроме <tex>s</tex> помещаются в множество <tex>M_2</tex>. Вершина <tex>s</tex> помещается в множество <tex>M_1</tex> (в любую из очередей). | Изначально все вершины, кроме <tex>s</tex> помещаются в множество <tex>M_2</tex>. Вершина <tex>s</tex> помещается в множество <tex>M_1</tex> (в любую из очередей). | ||
− | |||
'''Шаг алгоритма:''' выбирается вершина <tex>u</tex> из <tex>M_1</tex>. Если очередь <tex>M_1^{''}</tex> не пуста, то вершина берется из нее, иначе из <tex>M_1^{'}</tex>. Далее, для каждого ребра <tex>uv \in E</tex>: | '''Шаг алгоритма:''' выбирается вершина <tex>u</tex> из <tex>M_1</tex>. Если очередь <tex>M_1^{''}</tex> не пуста, то вершина берется из нее, иначе из <tex>M_1^{'}</tex>. Далее, для каждого ребра <tex>uv \in E</tex>: | ||
Строка 20: | Строка 19: | ||
* если <tex>v \in M_0</tex> и <tex>d_v > d_u + w_{uv}</tex>, то происходит релаксация ребра <tex>uv</tex> и <tex>v</tex> помещается в <tex>M_1^{''}</tex> | * если <tex>v \in M_0</tex> и <tex>d_v > d_u + w_{uv}</tex>, то происходит релаксация ребра <tex>uv</tex> и <tex>v</tex> помещается в <tex>M_1^{''}</tex> | ||
В конце шага помещаем вершину <tex>u</tex> в множество <tex>M_0</tex>. | В конце шага помещаем вершину <tex>u</tex> в множество <tex>M_0</tex>. | ||
− | |||
Алгоритм заканчивает работу, когда множество <tex>M_1</tex> становится пустым. | Алгоритм заканчивает работу, когда множество <tex>M_1</tex> становится пустым. | ||
Строка 56: | Строка 54: | ||
|proof= Не теряя общности, будем считать, что граф связен. Тогда алгоритм завершит работу, когда в <tex>M_0</tex> окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из <tex>M_0</tex> в <tex>M_1</tex> тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в <tex>M_0</tex>. Тогда за конечное число шагов все вершины окажутся в <tex>M_0</tex>. | |proof= Не теряя общности, будем считать, что граф связен. Тогда алгоритм завершит работу, когда в <tex>M_0</tex> окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из <tex>M_0</tex> в <tex>M_1</tex> тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в <tex>M_0</tex>. Тогда за конечное число шагов все вершины окажутся в <tex>M_0</tex>. | ||
}} | }} | ||
− | |||
{{Лемма | {{Лемма | ||
Строка 65: | Строка 62: | ||
Противоречие. | Противоречие. | ||
}} | }} | ||
− | |||
Из двух предыдущих лемм напрямую следует корректность алгоритма. | Из двух предыдущих лемм напрямую следует корректность алгоритма. | ||
Строка 71: | Строка 67: | ||
== Сложность == | == Сложность == | ||
− | В худшем случае алгоритм Левита работает за экспоненциальное время | + | В худшем случае алгоритм Левита работает за экспоненциальное время, например в полном графе <tex>K_n</tex> с достаточно большим n и весами <tex>w_{uv} = |
+ | \begin{cases} | ||
+ | 0, & u > 1 \\ | ||
+ | n - v + 1, & u = 1 \\ | ||
+ | \end{cases}</tex> при обработке <tex>i</tex>-ой вершины из множества <tex>M_2</tex> будет происходить релаксация <tex>i-1</tex> рёбер и их добавление в срочную <tex>M_1{''}</tex> очередь.Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм [[Алгоритм Форда-Беллмана|Форда Беллмана]] и не многим хуже алгоритма [[Алгоритм Дейкстры|Дейкстры]]. | ||
== Источники == | == Источники == |
Версия 11:59, 6 ноября 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.