Дан ориентированный или неориентированный взвешенный граф с n вершинами.
Алгоритм позволяет найти расстояние от каждой до каждой вершины и работает с отрицательными ребрами.
Алгоритм последовательно перебирает все такие I, через которые может лежать более короткий путь в V, чем который имеется сейчас.
Текущий (синий) путь и потенциально более короткий (красный).
Реализация
На вход программе подаётся граф, заданный в виде матрицы смежности — двумерного массива d[][] размера n х n, в котором каждый элемент задаёт длину ребра между соответствующими вершинами.
Предполагается, что если между двумя какими-то вершинами нет ребра, то в матрице смежности было записано какое-то большое число ( например INT_MAX в "limits.h", чтобы оно было больше длины любого пути в этом графе); тогда это ребро всегда будет невыгодно брать, и алгоритм сработает правильно.
Но при сложении двух бесконечностей может получиться переполнение int и на выходе будем иметь какое то отрицательно значение, поэтому неплохо бы подстраховаться дополнительной проверкой:
if (d[i][k] < INT_MAX && d[k][j] < INT_MAX)
В итоге алгоритм будет иметь вид:
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] < INT_MAX && d[k][j] < INT_MAX)
if(d[i][k]+d[k][j] < d[i][j])
d[i][j] = d[i][k] + d[k][j];
Например, дан граф:
Тогда начальная весовая матрица будет:
номера вершин |
1 |
2 |
3 |
1 |
0 |
8 |
5 |
2 |
3 |
0 |
INT_MAX |
3 |
INT_MAX |
2 |
0 |
после 1-ой итерации:
номера вершин |
1 |
2 |
3 |
1 |
0 |
8 |
5 |
2 |
3 |
0 |
8 |
3 |
INT_MAX |
2 |
0 |
после 2-ой итерации:
номера вершин |
1 |
2 |
3 |
1 |
0 |
8 |
5 |
2 |
3 |
0 |
8 |
3 |
5 |
2 |
0 |
после 3-ей итерации:
номера вершин |
1 |
2 |
3 |
1 |
0 |
7 |
5 |
2 |
3 |
0 |
8 |
3 |
5 |
2 |
0 |