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