Алгоритм Флойда
Алгоритм Флойда (алгоритм Флойда–Уоршелла) — алгоритм нахождения длин кратчайших путей между всеми парами вершин во взвешенном ориентированном графе. Работает корректно, если в графе нет циклов отрицательной величины, а в случае, когда такой цикл есть, позволяет найти хотя бы один такой цикл. Алгоритм работает за
времени и использует памяти. Разработан в 1962 году.Алгоритм
Постановка задачи
Дан взвешенный ориентированный граф
; , в котором вершины пронумерованы от до . Требуется найти матрицу кратчайших расстояний , в которой элемент либо равен длине кратчайшего пути из в , либо равен , если вершина не достижима из .Описание
Обозначим длину кратчайшего пути между вершинами
и , содержащего, помимо и , только вершины из множества как , .На каждом шаге алгоритма, мы будем брать очередную вершину (пусть её номер —
) и для всех пар вершин и вычислять . То есть, если кратчайший путь из в , содержащий только вершины из множества , проходит через вершину , то кратчайшим путем из в является кратчайший путь из в , объединенный с кратчайшим путем из в . В противном случае, когда этот путь не содержит вершины , кратчайший путь из в , содержащий только вершины из множества является кратчайшим путем из в , содержащим только вершины из множества .Код (в первом приближении)
for i = 1 to n for u = 1 to n for v = 1 to n
В итоге получаем, что матрица
и является искомой матрицей кратчайших путей, поскольку содержит в себе длины кратчайших путей между всеми парами вершин, имеющих в качестве промежуточных вершин вершины из множества , что есть попросту все вершины графа. Такая реализация работает за времени и использует памяти.Код (окончательный)
Утверждается, что можно избавиться от одной размерности в массиве
, т.е. использовать двумерный массив . В процессе работы алгоритма поддерживается инвариант , а, поскольку, после выполнения работы алгоритма , то тогда будет выполняться и .Утверждение: |
В течение работы алгоритма Флойда выполняются неравенства: . |
После инициализации все неравенства, очевидно, выполняются. Далее, массив может измениться только в строчке 5.Докажем второе неравенство индукцией по итерациям алгоритма. Пусть также — значение сразу после итерации.Покажем, что , зная, что .Рассмотрим два случая:
Пусть неравенство было нарушено, рассмотрим момент, когда оно было нарушено впервые. Пусть это была Итак -ая итерация и в этот момент изменилось значение и выполнилось . Так как изменилось, то (так как ранее ) (по неравенству треугольника) . — противоречие. |
func floyd(w): d = w for i = 1 to n for u = 1 to n for v = 1 to n d[u][v] = min(d[u][v], d[u][i] + d[i][v])
Данная реализация работает за время
, но требует уже памяти. В целом, алгоритм Флойда очень прост, и, поскольку в нем используются только простые операции, константа, скрытая в определении весьма мала.Пример работы
Вывод кратчайшего пути
Алгоритм Флойда легко модифицировать таким образом, чтобы он возвращал не только длину кратчайшего пути, но и сам путь. Для этого достаточно завести дополнительный массив
, в котором будет храниться номер вершины, в которую надо пойти следующей, чтобы дойти из в по кратчайшему пути.Модифицированный алгоритм
func floyd(w): d = w for i = 1 to n for u = 1 to n for v = 1 to n if d[u][i] + d[i][v] < d[u][v] d[u][v] = d[u][i] + d[i][v] next[u][v] = i
func getShortestPath(u, v):
if d[u][v] ==
print "No path found" // между вершинами u и v нет пути
c = u
while c != v
print c
c = next[c][v]
print v
Нахождение отрицательного цикла
Утверждение: |
При наличии цикла отрицательного веса в матрице появятся отрицательные числа на главной диагонали. |
Так как алгоритм Флойда последовательно релаксирует расстояния между всеми парами вершин | , в том числе и теми, у которых , а начальное расстояние между парой вершин равно нулю, то релаксация может произойти только при наличии вершины такой, что , что эквивалентно наличию отрицательного цикла, проходящего через вершину .
Из доказательства следует, что для поиска цикла отрицательного веса необходимо, после завершения работы алгоритма, найти вершину
, для которой , и вывести кратчайший путь между парой вершин . При этом стоит учитывать, что при наличии отрицательного цикла расстояния могут уменьшаться экспоненциально. Для предотвращения переполнения все вычисления стоит ограничивать снизу величиной , либо проверять наличие отрицательных чисел на главной диагонали во время подсчета.Источники информации
- Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ — 2-е изд — М.: Издательский дом «Вильямс», 2009. — ISBN 978-5-8459-0857-5.
- Википедия - Алгоритм Флойда — Уоршелла
- Wikipedia - Floyd–Warshall algorithm