Алгоритм Дейкстры

advertisement
Алгоритм Дейкстры
Пусть задан взвешенный орграф G, т. е. каждой его дуге сопоставлено некое число,
называемое весом или длиной этой дуги. Путем в графе называется некоторая
последовательность вершин такая, что каждые две соседние вершины соединены дугой;
вес или длина пути — сумма весов всех его дуг. Говорят, что вершина B достижима из
вершины A, если существует путь с началом A и концом B. Если вершина B достижима из
вершины A, то расстояние от A до B — длина минимального пути от A до B.
Пусть фиксирована некоторая вершина s, которую мы будем называть начальной. Наша
задача — для каждой вершины графа определить расстояние до нее от начальной
вершины либо указать, что данная вершина не достижима из начальной. Алгоритм
Дейкстры решает данную задачу за время O(N2) (в наиболее простой реализации), при
условии, что в графе нет дуг отрицательного веса.
Пусть в графе N вершин и он задан задан матрицей смежности
w : array [1..MAXN, 1..MAXN] of Integer;
Здесь a[i,j] = -1, если между вершинами i и j нет ребра, в противном случае a[i,j] равно
весу ребра между i и j.
Мы будем хранить массив
d : array [1..MAXN] of Integer;
В конце работы алгоритма число d[i] будет равно расстоянию от вершины s до вершины i,
либо -1, если i не достижима из s.
Кроме этого, на каждом шаге алгоритма мы будем делить вершины на пройденные и
непройденные, а также выделять одну вершину в качестве текущей:
b : array [1..MAXN] of Boolean;
c : Integer;
b[i] = true тогда и только тогда, когда вершина i пройдена; c — номер текущей вершины.
Алгоритм работает следующим образом. Вначале мы устанавливаем d[s]=0 и d[i]=-1 для i,
не равных s, объявляем s текущей вершиной и отмечаем все вершины как непройденные:
for i:=1 to n do
begin
d[i] := -1;
b[i] := false;
end;
d[s] := 0;
c := s;
Алгоритм состоит из шагов. На каждом шаге мы помечаем текущую вершину как
пройденную, производим улучшение из текущей вершины, а затем выбираем новую
текущую. Улучшение производится так: мы перебираем все вершины i, в которых есть
дуга из текущей вершины, и заменяем d[i] на d[c]+w[c,i] в случае, если d[i]=-1 либо
d[i]>d[c]+w[c,i]. Новая текущая вершина выбирается как непройденная вершина с
минимальным значением d, не равным -1. Если текущую вершину выбрать нельзя, то
алгоритм заканчивает свою работу.
while c<>-1 do
begin
b[c] := true;
for i:=1 to n do
if (w[c, i] <> -1) and ((d[i] = -1) or (d[i] > d[c] + w[c, i])) then
d[i] := d[c] + w[c, i];
c := -1;
for i:=1 to n do
if (not b[i]) and (d[i] <> -1) and ((c=-1) or (d[i] < d[c])) then
c := i;
end;
Пример: N = 5, w выглядит так:
-1 10 5 -1 -1
-1 -1 2 1 -1
-1 3 -1 9 2
-1 -1 -1 -1 4
7 -1 -1 6 -1
Вывод программы:
c
d
c
d
c
d
c
d
c
d
c
d
=
=
=
=
=
=
=
=
=
=
=
=
1
1:
3
1:
5
1:
2
1:
4
1:
-1
1:
0; 2: -1; 3: -1; 4: -1; 5: -1;
0; 2: 10; 3: 5; 4: -1; 5: -1;
0; 2: 8; 3: 5; 4: 14; 5: 7;
0; 2: 8; 3: 5; 4: 13; 5: 7;
0; 2: 8; 3: 5; 4: 9; 5: 7;
0; 2: 8; 3: 5; 4: 9; 5: 7;
Упражнения
1. Постройте пример графа, в котором есть дуги отрицательного веса и в котором
алгоритм Дейкстры работает неправильно.
2. Покажите, что если в графе есть цикл отрицательного веса, достижимый из
начальной вершины, то расстояние от начальной вершины до некоторых вершин
будет равно минус бесконечности.
3. Модифицируйте алгоритм Дейкстры так, чтобы он выводил не только расстояние
до вершин, но и кратчайшие пути до них.
Замечания
1. В случае, когда в графе есть дуги отрицательного веса, применяются другие
алгоритмы поиска кратчайших путей, в частности алгоритм Беллмана-Форда и
алгоритм Флойда.
2. Если хранить граф списком ребер, то с помощью кучи можно модифицировать
алгоритм так, чтобы он работал время O(M log N), M — число ребер.
Download