MAXimal | |
добавлено: 10 Jun 2008 19:41 Содержание [скрыть] Алгоритм Флойда-Уоршелла нахождения кратчайших путей между всеми парами вершинДан ориентированный или неориентированный взвешенный граф Предполагается, что граф не содержит циклов отрицательного веса (тогда ответа между некоторыми парами вершин может просто не существовать — он будет бесконечно маленьким). Этот алгоритм был одновременно опубликован в статьях Роберта Флойда (Robert Floyd) и Стивена Уоршелла (Варшалла) (Stephen Warshall) в 1962 г., по имени которых этот алгоритм и называется в настоящее время. Впрочем, в 1959 г. Бернард Рой (Bernard Roy) опубликовал практически такой же алгоритм, но его публикация осталась незамеченной. Описание алгоритмаКлючевая идея алгоритма — разбиение процесса поиска кратчайших путей на фазы. Перед Иными словами, перед Легко убедиться, что чтобы это свойство выполнилось для первой фазы, достаточно в матрицу расстояний Пусть теперь мы находимся на
Объединяя эти два случая, получаем, что на new_d[i][j] = min (d[i][j], d[i][k] + d[k][j]); Таким образом, вся работа, которую требуется произвести на Последнее замечание, которое следует сделать, — то, что можно не создавать отдельную матрицу Асимптотика алгоритма, очевидно, составляет РеализацияНа вход программе подаётся граф, заданный в виде матрицы смежности — двумерного массива Требуется, чтобы выполнялось for (int k=0; k<n; ++k) for (int i=0; i<n; ++i) for (int j=0; j<n; ++j) d[i][j] = min (d[i][j], d[i][k] + d[k][j]); Предполагается, что если между двумя какими-то вершинами нет ребра, то в матрице смежности было записано какое-то большое число (достаточно большое, чтобы оно было больше длины любого пути в этом графе); тогда это ребро всегда будет невыгодно брать, и алгоритм сработает правильно. Правда, если не принять специальных мер, то при наличии в графе рёбер отрицательного веса, в результирующей матрице могут появиться числа вида for (int k=0; k<n; ++k) for (int i=0; i<n; ++i) for (int j=0; j<n; ++j) if (d[i][k] < INF && d[k][j] < INF) d[i][j] = min (d[i][j], d[i][k] + d[k][j]); Восстановление самих путейЛегко поддерживать дополнительную информацию — так называемых "предков", по которым можно будет восстанавливать сам кратчайший путь между любыми двумя заданными вершинами в виде последовательности вершин. Для этого достаточно кроме матрицы расстояний Случай вещественных весовЕсли веса рёбер графа не целочисленные, а вещественные, то следует учитывать погрешности, неизбежно возникающие при работе с типами с плавающей точкой. Применительно к алгоритму Флойда неприятным спецэффектом этих погрешностей становится то, что найденные алгоритмом расстояния могут уйти сильно в минус из-за накопившихся ошибок. В самом деле, если на первой фазе имела место ошибка Чтобы этого не происходило, сравнения в алгоритме Флойда следует делать с учётом погрешности: if (d[i][k] + d[k][j] < d[i][j] - EPS) d[i][j] = d[i][k] + d[k][j]; Случай отрицательных цикловЕсли в графе есть циклы отрицательного веса, то формально алгоритм Флойда-Уоршелла неприменим к такому графу. На самом же деле, для тех пар вершин Для тех же пар вершин, ответа для которых не существует (по причине наличия отрицательного цикла на пути между ними), алгоритм Флойда найдёт в качестве ответа какое-то число (возможно, сильно отрицательное, но не обязательно). Тем не менее, можно улучшить алгоритм Флойда, чтобы он аккуратно обрабатывал такие пары вершин и выводил для них, например, Для этого можно сделать, например, следующий критерий "не существования пути". Итак, пусть на данном графе отработал обычный алгоритм Флойда. Тогда между вершинами Кроме того, при использовании алгоритма Флойда для графов с отрицательными циклами следует помнить, что возникающие в процессе работы расстояния могут сильно уходить в минус, экспоненциально с каждой фазой. Поэтому следует принять меры против целочисленного переполнения, ограничив все расстояния снизу какой-нибудь величиной (например, Более подробно об этой задаче см. отдельную статью: "Нахождение отрицательного цикла в графе".
|