Алгоритм Флойда
Версия от 00:25, 22 декабря 2010; Kirelagin (обсуждение | вклад) (Почти готово. Осталось добавить пример)
Эта статья находится в разработке!
Алгоритм Флойда (алгоритм Флойда–Уоршелла) — динамический алгоритм нахождения длин кратчайших путей между всеми парами вершин взвешенного ориентированного графа. Разработан в 1962 году.
Содержание
Алгоритм
Пусть дан граф
; ; вершины пронумерованы от до .Обозначим длину кратчайшего пути между вершинами
и , содержащего, помимо самих вершин и , только вершины с номерами как . Понятно, что .На каждом шаге алгоритма, мы будем брать очередную вершину (пусть, её номер
) и для всех пар вершин и вычислять . Т.е., если кратчайший путь из в , содержащий только вершины с номерами , проходит через вершину , то пройдём сначала из в , затем из в , иначе ничего менять не будем.Код (в первом приближении)
# Инициализация d[0] = w # Основная часть for i in {1..n}: for u in {1..n}: for v in {1..n}: d[i][u][v] = min(d[i-1][u][v], d[i-1][u][i] + d[i-1][i][v])
Код (окончательный)
Заметим, что для заполнения
-того слоя массива используются только значения из -го слоя. Таким образом, от первого индекса вообще можно отказаться.# Инициализация d = w # Основная часть for i in {1..n}: for u in {1..n}: for v in {1..n}: d[u][v] = min(d[u][v], d[u][i] + d[i][v])
Алгоритм всегда завершит работу за
— как не сложно видеть, три вложенных цикла выполняются по раз каждый.Пример работы
Здесь пример, да
Вывод кратчайшего пути
Алгоритм Флойда легко модифицировать таким образом, чтобы он возвращал не только длину кратчайшего пути, но и сам путь. Для этого достаточно завести дополнительный массив
, в котором будет храниться номер вершины, в которую надо пойти следующей, чтобы дойти из в по кратчайшему пути.Модифицированный алгоритм
# Инициализация d = w t[u][v] = v если есть ребро uv # Основная часть for i in {1..n}: for u in {1..n}: for v in {1..n}: if (d[u][i] + d[i][v]) < d[u][v]: d[u][v] = d[u][i] + d[i][v] t[u][v] = t[u][i]
# Вывод кратчайшего пути def get_shortest_path(u, v): if d[u][v] == inf: raise NoPath # Из u в v пути нет c = u while c != v: yield c c = t[c][v] yield v