Алгоритм Флойда — различия между версиями
Kirelagin (обсуждение | вклад) (Почти готово. Осталось добавить пример) |
Kirelagin (обсуждение | вклад) (Добавлен пример) |
||
Строка 39: | Строка 39: | ||
=== Пример работы === | === Пример работы === | ||
− | + | {|style="text-align:center;" | |
+ | | <tex>i = 0</tex> || <tex>i = 1</tex> || <tex>i = 2</tex> || <tex>i = 3 </tex> || <tex>i = 4</tex> | ||
+ | |- | ||
+ | | [[Файл:Floyd_step0.png]] || [[Файл:Floyd_step1.png]] || [[Файл:Floyd_step2.png]] || [[Файл:Floyd_step3.png]] || [[Файл:Floyd_step4.png]] | ||
+ | |- | ||
+ | | <tex>\begin{pmatrix} | ||
+ | \times & 1 & 6 & \infty \\ | ||
+ | \infty & \times & 4 & 1 \\ | ||
+ | \infty & \infty & \times & \infty \\ | ||
+ | \infty & \infty & 1 & \times \\ | ||
+ | \end{pmatrix}</tex> | ||
+ | || <tex>\begin{pmatrix} | ||
+ | \times & 1 & 6 & \infty \\ | ||
+ | \infty & \times & 4 & 1 \\ | ||
+ | \infty & \infty & \times & \infty \\ | ||
+ | \infty & \infty & 1 & \times \\ | ||
+ | \end{pmatrix}</tex> | ||
+ | || <tex>\begin{pmatrix} | ||
+ | \times & 1 & \bf{5} & \bf{2} \\ | ||
+ | \infty & \times & 4 & 1 \\ | ||
+ | \infty & \infty & \times & \infty \\ | ||
+ | \infty & \infty & 1 & \times \\ | ||
+ | \end{pmatrix}</tex> | ||
+ | || <tex>\begin{pmatrix} | ||
+ | \times & 1 & 5 & 2 \\ | ||
+ | \infty & \times & 4 & 1 \\ | ||
+ | \infty & \infty & \times & \infty \\ | ||
+ | \infty & \infty & 1 & \times \\ | ||
+ | \end{pmatrix}</tex> | ||
+ | || <tex>\begin{pmatrix} | ||
+ | \times & 1 & \bf{3} & 2 \\ | ||
+ | \infty & \times & \bf{2} & 1 \\ | ||
+ | \infty & \infty & \times & \infty \\ | ||
+ | \infty & \infty & 1 & \times \\ | ||
+ | \end{pmatrix}</tex> | ||
+ | |} | ||
== Вывод кратчайшего пути == | == Вывод кратчайшего пути == |
Версия 01:43, 22 декабря 2010
Эта статья находится в разработке!
Алгоритм Флойда (алгоритм Флойда–Уоршелла) — динамический алгоритм нахождения длин кратчайших путей между всеми парами вершин взвешенного ориентированного графа. Разработан в 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