Алгоритм Левита — различия между версиями
Lehanyich (обсуждение | вклад) |
Lehanyich (обсуждение | вклад) |
||
Строка 29: | Строка 29: | ||
<tex>M_1^{'}</tex>.push(<tex>s</tex>) | <tex>M_1^{'}</tex>.push(<tex>s</tex>) | ||
'''for''' <tex>u : u \neq s</tex> '''and''' <tex>u \in V</tex> | '''for''' <tex>u : u \neq s</tex> '''and''' <tex>u \in V</tex> | ||
− | <tex>M_2</tex>. | + | <tex>M_2</tex>.add(<tex>u</tex>) |
'''while''' <tex>M_1^{'} \neq \varnothing</tex> '''and''' <tex>M_1^{''} \neq \varnothing</tex> | '''while''' <tex>M_1^{'} \neq \varnothing</tex> '''and''' <tex>M_1^{''} \neq \varnothing</tex> | ||
− | + | <tex>u=(M_1^{''} = \varnothing</tex> <tex>?</tex> <tex>M_1^{'}</tex>.pop() <tex>:</tex> <tex>M_1{''}</tex>.pop()<tex>)</tex> | |
− | |||
− | |||
− | |||
− | |||
'''for''' <tex>v : uv \in E</tex> | '''for''' <tex>v : uv \in E</tex> | ||
'''if''' <tex>v \in M_2</tex> | '''if''' <tex>v \in M_2</tex> | ||
Строка 41: | Строка 37: | ||
<tex>M_2</tex>.remove(<tex>v</tex>) | <tex>M_2</tex>.remove(<tex>v</tex>) | ||
<tex>d[v] =</tex> min(<tex>d[v], d[u] + w_{uv}</tex>) | <tex>d[v] =</tex> min(<tex>d[v], d[u] + w_{uv}</tex>) | ||
− | '''else if''' v <tex>\in M_1</tex> | + | '''else if''' <tex>v</tex> <tex>\in M_1</tex> |
<tex>d[v] =</tex> min(<tex>d[v], d[u] + w_{uv}</tex>) | <tex>d[v] =</tex> min(<tex>d[v], d[u] + w_{uv}</tex>) | ||
'''else if''' <tex>v \in M_0</tex> '''and''' <tex>d[v] > d[u] + w_{uv}</tex> | '''else if''' <tex>v \in M_0</tex> '''and''' <tex>d[v] > d[u] + w_{uv}</tex> | ||
Строка 47: | Строка 43: | ||
<tex>M_0</tex>.remove(<tex>v</tex>) | <tex>M_0</tex>.remove(<tex>v</tex>) | ||
<tex>d[v] = d[u] + w_{uv}</tex> | <tex>d[v] = d[u] + w_{uv}</tex> | ||
− | <tex>M_0</tex>. | + | <tex>M_0</tex>.add(<tex>u</tex>) |
== Доказательство == | == Доказательство == | ||
Строка 84: | Строка 80: | ||
* [[Обход в ширину]] | * [[Обход в ширину]] | ||
− | == Источники == | + | == Источники информации== |
* [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 MAXimal :: algo :: Алгоритм Левита] |
* И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231. | * И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231. | ||
[[Категория: Алгоритмы и структуры данных]] | [[Категория: Алгоритмы и структуры данных]] | ||
[[Категория: Кратчайшие пути в графах]] | [[Категория: Кратчайшие пути в графах]] |
Версия 21:21, 7 ноября 2015
Алгоритм Левита (англ. Levit's algorithm) находит расстояние от заданной вершины
до всех остальных. Позволяет работать с ребрами отрицательного веса при отсутствии отрицательных циклов.Алгоритм
Пусть
— текущая длина кратчайшего пути до вершины . Изначально, все элементы , кроме -го равны бесконечности; .Разделим вершины на три множества:
- — вершины, расстояние до которых уже вычислено (возможно, не окончательно),
- очереди: — вершины, расстояние до которых вычисляется. Это множество в свою очередь делится на две
- — основная очередь,
- — срочная очередь;
- — вершины, расстояние до которых еще не вычислено.
Изначально все вершины, кроме
помещаются в множество . Вершина помещается в множество (в любую из очередей).Шаг алгоритма: выбирается вершина
из . Если очередь не пуста, то вершина берется из нее, иначе из . Для каждого ребра возможны три случая:- , то переводится в конец очереди . При этом (производится релаксация ребра ),
- , то происходит релаксация ребра ,
- и , то происходит релаксация ребра и помещается в .
В конце шага помещаем вершину
в множество .Алгоритм заканчивает работу, когда множество
становится пустым.Псевдокод
for.push( ) for and .add( ) while and .pop() .pop() for if .push( ) .remove( ) min( ) else if min( ) else if and .push( ) .remove( ) .add( )
Доказательство
Лемма: |
Алгоритм отработает за конечное время |
Доказательство: |
Не теряя общности, будем считать, что граф связен. Тогда алгоритм завершит работу, когда в | окажутся все вершины. Так как в исходном графе нет отрицательных циклов, то для каждой вершины существует кратчайший путь. Тогда расстояние до каждой вершины может уменьшится только конечное число раз и, как следствие, вершина будет переведена из в тоже конечное число раз. С другой стороны, на каждом шаге текущая вершина гарантированно помещается в . Тогда за конечное число шагов все вершины окажутся в .
Лемма: |
В конце работы алгоритма не найдется такое ребро , что его релаксация будет успешной |
Доказательство: |
Предположим обратное. Тогда рассмотрим 2 случая:
|
Из двух предыдущих лемм напрямую следует корректность алгоритма.
Сложность
В плохих случаях алгоритм Левита работает очень долго. Например, в полном графе лексикографическом порядке. Добавление вершины в очередь и последующая её обработка влекут добавление из в всех её предыдущих вершин, начиная со -ой; дойдя до вершины , в снова добавятся вершины меньше (кроме первой). Таким образом, вершину добавят в раз, всего в будет добавлений. В очень плохих случаях вершина может помещаться в очередь до раз, что даёт экспоненциальное время. Однако, на реальных графах алгоритм Левита работает быстрее, чем алгоритм Форда Беллмана и не многим уступает алгоритму Дейкстры.
с достаточно большим и весами , рёбра идут вСм. также
- Алгоритм A*
- Алгоритм Дейкстры
- Алгоритм Джонсона
- Алгоритм Флойда
- Алгоритм Форда-Беллмана
- Обход в ширину
Источники информации
- Википедия — Алгоритм Левита
- MAXimal :: algo :: Алгоритм Левита
- И. В. Романовский, Дискретный анализ, ISBN 5-7940-0138-0; 2008 г., 4 издание, стр. 229-231.