Алгоритм Флойда — различия между версиями
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





