Zaawansowane algorytmy i struktury danych/Wykład 6: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Sank (dyskusja | edycje)
Nie podano opisu zmian
Sank (dyskusja | edycje)
Nie podano opisu zmian
Linia 1: Linia 1:
== Abstrakt ==


W wykładzie tym zajmiemy się problemem obliczanie odległości w
grafie między wszystkimi parami wierzchołków w grafie ważonym
skierowanym <math>G=(V,E)</math>. Przedstawimy trzy algorytmu
rozwiązujące ten problem:
* algorytm wykorzystujący mnożenie macierzy działający w czasie <math>O(|V|^3\log
|V|</math>,
* algorytm Floyda-Warshalla działający w czasie <math>O(|V|^3)</math>,
* algorytm Johnsona działający w czasie <math>O(V|^2 \log |V| +
|V||E|)</math>.
== Problem najkrótszych ścieżek między wszystkimi parami
wierzchołków ==
Problem najkrótszych ścieżek między wszystkimi parami wierzchołków
można rozwiązać, wykonując <math>|V|</math> razy algorytm dla
problemu najkrótszych ścieżek z jednego wierzchołka. Jeżeli w grafie
wagi krawędzi są nieujemne to możemy użyć algorytmu Dijkstry.
Najszybsza implementacji algorytmu Dijskstry wykorzystująca kopce
Fibonacciego działa w czasie <math>O(|V| \log |V| + |E|)</math>, co
daje nam algorytm rozwiązujący problem policzenia odległości między
wszystkimi parami wierzchołków działający w czasie <math>O(|V|^2
\log |V| + |V||E|)</math>.
Jednakże tego rozwiązania nie możemy użyć jeżeli w grafie wagi
krawędzi mogą być ujemne. W takim przypadku możemy użyć [[Wykład
5#algorytm_Bellmana-Forda|algorytm Bellmana-Forda]]. Otrzymamy wtedy
algorytm działający w czasie <math>O(|V|^2|E|</math>. W rozdziale
tym zaprezentujemy bardziej efektywne rozwiązania dla tego problemu.
W rozdziale tym będziemy zakładać, że algorytmy na wejściu otrzymują
{{kotwica|macierz_wag|''macierz wag''}} <math>W</math> rozmiaru <math>n\times n</math>
reprezentującą wagi krawędzi <math>n</math>-wierzchołkowego grafu
<math>G = (V,E)</math>. Dla macierzy tej zachodzi:
<center><math>
w_{i,j} = \begin{cases}
0, & \mathrm{jeśli } i=j,
\mathrm{waga krawędzi } (i,j), & \matkrm{jeśli } i\neq j \mathrm{ i } (i,j)\in E,
\infty, & \matkrm{jeśli } i\neq j \mathrm{ i } (i,j)\neq E.
\end{cases}
</math></center>
W problemie najkrótszych ścieżek między wszystkimi parami
wierzchołków  chcemy wyznaczyć macierz <math>D</math> rozmiaru
<math>n \times n</math> taką, że <math>d_{i,j}</math> jest równe
odległości <math>\delta(i,j)</math> z wierzchołka <math>i</math> do
wierzchołka <math>j</math>. Chcemy także wyznaczyć dla każdego
wierzchołka <math>v</math> [[Wykład 5#drzewo_najkrótszych_ścieżek|drzewo najkrótszych ścieżek]]
<math>T_v</math> ukorzenione w <math>v</math>. Podobnie jak w
poprzednim rozdziale drzewo <math>T_v</math> możemy kodować dla
każdego wierzchołka przy pomocy funkcji poprzedników
<math>\pi_{v}</math>. Ponieważ tutaj interesuje nas wiele drzew to
łatwiej będzie nam używać {{kotwica|macierz_poprzedników|'''macierzy
poprzedników''}} <math>\Pi</math>. Macierz tą definiujemy używając
funkcji <math>\pi_v</math> w następujący sposób:
<center><math>
\Pi_{v,u} = \pi_v(u).
</math></center>
W pozostałej części tego wykładu zajmiemy się tylko wyznaczaniem
macierzy odległości <math>D</math>. Jak to zostało pokazane w
[[Ćwiczenia 5/Zadanie 3|Zadaniu 3]] do poprzedniego wykładu znając
odległości w grafie drzewo najkrótszych ścieżek można wyznaczyć w
czasie <math>O(|E|)</math>, a więc <math>|V|</math> drzew możemy
wyliczyć w czasie <math>O(|E||V|)</math>. Czas ten jest mniejszy niż
czas działania wszystkich prezentowanych w tym wykładzie algorytmów,
więc bez straty ogólności, a zyskując na prostocie prezentacji
możemy ograniczyć się tylko do wyznaczenia macierzy odległości
<math>D</math>.
Co więcej będziemy zakładać, że w grafie nie ma ujemnych cykli.
Ujemne cykle można wykryć w czasie <math>O(|V||E|)</math> przy
użyciu [[wykład 5/algorytm_Bellmana-Forda|Algorytmu
Bellmana-Forda]]. Zobacz [[Ćwiczenia 5#Zadanie 4| Zadanie 4]] do
Wykładu 4.
== Najkrótsze ścieżki i mnożenie macierzy ==
Załóżmy, że dane mamy dwie [[#macierz_wag|macierze wag]]
<math>C</math> oraz <math>D</math> rozmiaru <math>n\times n</math>.
Dla macierzy tych definiujemy operację <math>\times_{\min}</math>l
{{kotwica|liczyn_odległości|'''iloczynu odległości'''}}, której
wynikiem jest także macierz rozmiaru <math>n \times n</math>,
zdefiniowana jako:
{{wzor|wzór_1|1|3=
<math>
(C \times_{\min} D)_{i,j} = \min_{k = 1,\ldots,n} C_{i,k} + D_{k,j}.
</center>
}}
{{wniosek|wniosek_konkatenacja|1|3=
Jeżeli założymy, że <math>C</math> i <math>D</math> opisują
minimalne wagi odpowiednio zbioru ścieżek odpowiednio
<math>\Pi_{C}</math> i <math>\Pi_{D}</math> w pewnym grafie
<math>G</math>, to iloczyn odległości wyznacza minimalne wagi zbioru
ścieżek powstałego z konkatenacji ścieżek ze zbioru
<math>\Pi_{C}</math> ze ścieżkami zbioru <math>\Pi_{D}</math>.
}}
Pokażemy teraz, że produkt odległości jest operacją łączną.
{{lemat|io_łączny|2|3=
Dla macierzy <math>C</math>, <math>D</math> i <math>E</math>
rozmiaru <math>n\times n</math>zachodzi:
<center><math>
\left(C \times_{\min} D \right) \times_{min}  E = C \times_{\min} \left( D  \times_{min} E \right).
</math></center>
}}
{{dowod||| Powyższa równość wynika wprost z [[#wzór_1|wzoru (1))]] oraz
przemienności operacji <math>\min</math>.
}}
Co więcej produkt odległości jest przemienny względem dodawania.
{{lemat|io_przemienny|3|3= Dla macierzy <math>C</math>, <math>D</math>
i <math>E</math> rozmiaru <math>n\times n</math>zachodzi:
<center><math> C \times_{\min} \left(D  + E \right)= C \times_{\min}
D +  C  \times_{min} E, </math></center>
oraz
<center><math>
\left(D  + E \right) \times_{\min} C = D \times_{\min} C +  E  \times_{min} C.
</math></center> }} {{dowod||| Te dwie równości wynikają ponownie z
[[#wzór_1|wzoru (1)]] oraz przemienności operacji <math>\min</math>
względem dodawania. }}
Zdefiniujmy macierz <math>I_{\min}</math> rozmiaru <math>n \times
n</math> jako: <center><math> \left(I_{\min}\right)_{i,j} =
\begin{cases} 0, & \mbox{jeśli } i=j, \infty, & \mbox{jeśli } i \neq
j.
\end{cases}
</math></center>
Macierz ta jest jedynką dla iloczynu odległości.
{{lemat|io_jedynka|4|3= Dla macierzy <math>C</math> rozmiaru <math>n
\times n</math> zachodzi:
<center><math> I_{\min} \times_{\min} C = C \times_{\min} I_{\min} =
C. </math></center> }}
{{dowód||| Mamy
<center><math> \left(\I_{\min} \times_{\min} C\right)_{i,j} =
\min_{k = 1,\ldots,n} \left(I_{\min}\right)_{i,k} + C_{k,j} =
</math></center>
ponieważ wszystkie elementy <math>\left(I_{\min}\right)_{i,k}</math>
równe są <math>\infty</math> oprócz elementu <math>i = k</math>, to
możemy je pominąć w operacji <math>\min</math> i:
<center><math> = \min_{k = i} \left(I_{\min}\right)_{i,k} + C_{k,j}
= I_{i,i} + C_{i,j} = C_{i,j}. </math></center> }}
Łączność iloczynu odległości ma dla nas bardzo ważne konsekwencję i
pozwoli nam na konstrukcję algorytmu obliczania odległości w grafie
między wszystkimi parami wierzchołków działającego w czasie
<math>O(n^{3}\log n)</math>. Niech <math>W</math> będzie
[[#macierz_wag|macierzą wag]] grafu <math>G = (V,E)</math>. Rozważmy
macierz <math>W^m</math> zdefiniowaną jako:
<center>
<math>
W^{m} = \begin{cases}
I_{\min}, &\mbox{jeżeli } m=0,\\
W \times_{\min} W^{m-1}, &\mbox{jeżeli } m>0.
</math>
</center>
Pokażemy teraz, że macierz <math>W^m</math> opisuje odległości
między wierzchołkami grafu ale tylko dla ścieżek używających mniej niż
<math>m</math> krawędzi.
{{lemat|potęgi_odległości|5|3=
Element <math>W_{i,j}^{m}</math> macierzy <math>W^{m}</math> zadaje
najmniejszą wagę ścieżki wychodzącej z wierzchołka <math>i</math> do
wierzchołka <math>j</math> spośród ścieżek, które zawierają
mniej niż <math>m</math> krawędzi, tzn.:
<center><math>
w_{i,j}^{m} = \begin{cases}
\min\{w(p): p \mbox{ ścieżka o długości } \le m \mboc{ z } u \mbox{ do } v\}, & \mbox{jeżeli istnieje ścieżka o długości } \le m \mboc{ z } u \mbox{ do } v,\\
\infty & \mbox{w przeciwnym przypadku.}
\end{cases}
</math></center>
}}
{{dowód|||3= Tezę tą udowodnimy przez indukcję po <math>m</math>.
Dla danego wierzchołka istnieją dla niech tylko ścieżki długości
zero prowadzące do niego samego, a więc dla <math>m=0</math> teza
wynika wprost z definicji macierzy <math>W^0</math>.
Załóżmy teraz, że teza zachodzi dla <math>m >0</math>. Mamy wtedy
<math>W^{m+1} = W \times_{\min} W^{m}</math>. Zauważmy, że ze
definicji [[#macierz_wag|macierzy wag]] <math>W</math> opisuje
ścieżki używające <math>\le 1</math> krawędź. Korzystając teraz
z [[wniosek_konkatenacja|Wniosku 1]] otrzymujemy tezę dla <math>m+1</math>.
}}
Zajmiemy się teraz konstrukcją algorytmu obliczającego najkrótsze
ścieżki w grafie. W tym celu będziemy potrzebowali jeszcze udowodnić
następujące dwa lematy.
{{lemat|lemat_6|6|3=
Jeżeli w grafie <math>G=(V,E)</math>, w którym wagi krawędzi zadane
są macierzą <math>W</math> nie istnieje cykl o ujemnej wadze
to:
<center><math>
\delta(u,v) = W^{(k)}_{u,v}, \mbox{ dla } k \ge n-1.
</math></center>
}}
{{dowód|||3= Jeżeli w grafie nie istnieje cykl o ujemnej wadze, to
wszystkie najkrótsze ścieżki są ścieżkami prostymi, a więc mają
długość co najwyżej <math>n-1</math>. Z [[potęgi_odległości|Lematu
5]] wynika więc że odległości tych ścieżek są dobrze wyznaczone w
<math>W^{k}</math> dla <math>k \le n-1</math>. }}
Zauważmy, że iloczyn odległości dwóch macierzy
możemy policzyć w czasie <math>O(|V|^3)</math> wykorzystując następujący
algorytm.
{{algorytm|algorytm_iloczyn_odległości|Mnożenia macierzy odległości
  MNOŻENIE-ODLEGŁOŚCI(C,D)
  1  <math>E</math> macierz rozmiaru <math>n \times n</math>
  2  '''for''' <math>i = 0</math> '''to''' <math>n-1</math> '''do'''
  3    '''for''' <math>j = 0</math> '''to''' <math>n-1</math> '''do'''
  4      <math>e_{i,j} = \infty</math>
  5      '''for''' <math>k =0</math> '''to''' <math>n-1</math> '''do'''
  6        e_{i,j} = \min(c_{i,k} + d_{k,j}, e_{i,j})
  7  '''return''' D'
}}
Ponieważ operacja iloczynu odległości jest łączna to możemy
wykorzystać [[algorytm_szybkiego_potęgowania|algorytm szybkiego
potęgowania]] i policzyć odległości przy pomocy następującego
algorytmu.
{{algorytm|algorytm_apsp_mnozenie|Algorytm obliczania odległości
między wszystkimi parami wierzchołków I|3=
  ODLEGŁÓŚCI-I(W)
  1  <math>D = W</math>,
  2  <math>k = 1</math>
  3 '''while''' <math>n-1 > k</math> '''do'''
  4  <math>D = </math>MNOŻENIE-ODLEGŁOŚCI<math>(D,D)</math>
  5  <math>m = 2m</math>
  7  '''return''' <math>D</math>
}}
Poprawności tego algorytmu wynika wprost z [[lemat_6|Lematu 6]] ponieważ
na zakończenie algorytmu <math>D = W^{m}</math> i <math>m > n-1</math>.
== Algorytm Floyda-Warshalla ==
W algorytmie Floyda-Warshalla wykorzystamy inną cechę najkrótszych
ścieżek niż ta użyta w algorytmie z wykorzystaniem
[[#iloczyn_odległości|iloczynu odległości]]. W poprzednim algorytmie
konstruowaliśmy coraz dłuższe ścieżki, natomiast tutaj będziemy
konstruować ścieżki przechodzące przez coraz większy zbiór
wierzchołków. Wierzchołkiem
{{kotwica|wierzchołek_wewnetrzny|'''wewnetrznym'''} ścieżki <math>p
= (v_0, \ldots, v_l)</math> jest każdy wierzchołek na ścieżce
<math>p</math> różny od jej początku <math>v_0</math> i końca
<math>v_l</math>.
Niech zbiorem wierzchołków grafu <math>G</math> będzie <math>V =
\{1,\ldots,n\}</math>. Niech <math>d_{i,j}^{(k)}</math> dla <math>k =
0,\ldots, n</math> oznacza najmniejszą wagę ścieżki z <math>i</math>
do <math>j</math>, spośród ścieżek których wierzchołki wewnętrzne
należą do zbioru <math>\{v_1, \ldots,v_{k}</math>. Pokażemy następujący
rekurencyjny wzór na <math>D^{(k)}</math>.
{{lemat|lemat_7|7|3=
Dla <math>k=0,\ldots, n</math> zachodzi:
<center><math>
d_{i,j}^{(k)} = \begin{cases}
w_{i,j}, & \mbox{jeżeli } k=0,\\
\min( d_{i,j}^{(k-1)}, d_{i,k}^{(k-1)} + d_{k,j}^{(k-1)}, & \mbox{jeżeli } k \ge 1.
\end{cases}
</math></center>
}}
{{dowód|||3= Dla <math>k=0</math> poprawność powyższego wzoru wynika
bezpośrednio z definicji <math>D^0</math>. Dla <math>k>0</math>
musimy pokazać, że
{{wzor|wzor_2|2
<center><math>
d_{i,j}^{(k)} = \min( d_{i,j}^{(k-1)}, d_{i,k}^{(k-1)} + d_{k,j}^{(k-1)}).
</math></center>
}}
Niech <math>p</math> będzie najkrótszą ścieżką z <math>i</math> do <math>j</math>,
której wierzchołki wewnętrzne należą do zbioru <math>\{v_1,\ldots,v_k\}</math>. Mamy dwa przypadki:
* Wierzchołek <math>v_k</math> nie leży na ścieżce <math>p</math>. Wtedy zachodzi
<math>d_{i,j}^{(k)} = p(w) = d_{i,j}^{(k-1)}</math>. Ponieważ <math>p</math> jest najkrótszą
ścieżką to także <math>p(w) \le d_{i,k}^{(k-1)} + d_{k,j}^{(k-1)}</math> i powyższy wzór zachodzi.
* Jeżeli wierzchołek <math>v_k</math> należy do ścieżki <math>p</math>,  to występuje
on dokładnie raz i możemy podzielić <math>p</math> na dwie ścieżki
<math>p_1</math> z <math>i</math> do <math>k</math> oraz
<math>p_2</math> z <math>k</math> do <math>j</math>. Ścieżki
<math>p_1</math> i <math>p_2</math> nie zawierają wierzchołka
<math>v_k</math> jako wierzchołka wewnętrznego. Ponieważ są to
podścieżki najkrótszej ścieżki, więc same też są najkrótsze.
Zachodzi więc dla nich <math>w(p_1) = d_{i,k}^{(k-1)}</math> oraz
<math>w(p_2) = d_{k,j}^{(k-1)}</math>. Otrzymujemy więc
<math>d_{i,j}^{(k)} = w(p) = w(p_1) + w(p_2) = d_{i,k}^{(k-1)} +
d_{k,j}^{(k-1)}</math>. Ponieważ <math>p</math> jest najkrótszą ścieżką
to <math>p(w) \le d_{i,j}^{(k-1)}</math> i wzór zachodzi także w tym przypadku.
<!-- TODO: może  jakiś rysunek -->
}}
Wykorzystując [[#wzor_2| wzór (2)]] możemy skonstruować następujący
algorytm obliczający w czasie <math>O(|V|^3)</math> odległości
między wszystkimi parami wierzchołków.
{{algorytm|algorytm_Floyda-Warshalla|Algorytm Floyda-Warshalla|3=
między wszystkimi parami wierzchołków I
  ODLEGŁÓŚCI-II(W)
  1  <math>D^{(0)} = W</math>,
  2  '''for''' <math>k = 1</math> '''to''' <math>n</math> '''do'''
  3    '''for''' <math>i = 1</math> '''to''' <math>n</math> '''do'''
  4      '''for''' <math>j = 1</math> '''to''' <math>n</math> '''do'''
  5        <math>d_{i,j}^{(k)} = \min(d_{i,j}^{(k-1)}, d_{i,k}^{(k-1)} + d_{k,j}^{(k-1)})</math>
  6  '''return''' <math>D^{(n)}</math>
}}

Wersja z 22:55, 21 lip 2006

Abstrakt

W wykładzie tym zajmiemy się problemem obliczanie odległości w grafie między wszystkimi parami wierzchołków w grafie ważonym skierowanym G=(V,E). Przedstawimy trzy algorytmu rozwiązujące ten problem:

  • algorytm wykorzystujący mnożenie macierzy działający w czasie O(|V|3log|V|,
  • algorytm Floyda-Warshalla działający w czasie O(|V|3),
  • algorytm Johnsona działający w czasie O(V|2log|V|+|V||E|).

== Problem najkrótszych ścieżek między wszystkimi parami wierzchołków ==

Problem najkrótszych ścieżek między wszystkimi parami wierzchołków można rozwiązać, wykonując |V| razy algorytm dla problemu najkrótszych ścieżek z jednego wierzchołka. Jeżeli w grafie wagi krawędzi są nieujemne to możemy użyć algorytmu Dijkstry. Najszybsza implementacji algorytmu Dijskstry wykorzystująca kopce Fibonacciego działa w czasie O(|V|log|V|+|E|), co daje nam algorytm rozwiązujący problem policzenia odległości między wszystkimi parami wierzchołków działający w czasie O(|V|2log|V|+|V||E|).

Jednakże tego rozwiązania nie możemy użyć jeżeli w grafie wagi krawędzi mogą być ujemne. W takim przypadku możemy użyć [[Wykład 5#algorytm_Bellmana-Forda|algorytm Bellmana-Forda]]. Otrzymamy wtedy algorytm działający w czasie O(|V|2|E|. W rozdziale tym zaprezentujemy bardziej efektywne rozwiązania dla tego problemu.

W rozdziale tym będziemy zakładać, że algorytmy na wejściu otrzymują macierz wag W rozmiaru n×n reprezentującą wagi krawędzi n-wierzchołkowego grafu G=(V,E). Dla macierzy tej zachodzi:


Parser nie mógł rozpoznać (nieznana funkcja „\begin{cases}”): {\displaystyle w_{i,j} = \begin{cases} 0, & \mathrm{jeśli } i=j, \mathrm{waga krawędzi } (i,j), & \matkrm{jeśli } i\neq j \mathrm{ i } (i,j)\in E, \infty, & \matkrm{jeśli } i\neq j \mathrm{ i } (i,j)\neq E. \end{cases} }


W problemie najkrótszych ścieżek między wszystkimi parami wierzchołków chcemy wyznaczyć macierz D rozmiaru n×n taką, że di,j jest równe odległości δ(i,j) z wierzchołka i do wierzchołka j. Chcemy także wyznaczyć dla każdego wierzchołka v drzewo najkrótszych ścieżek Tv ukorzenione w v. Podobnie jak w poprzednim rozdziale drzewo Tv możemy kodować dla każdego wierzchołka przy pomocy funkcji poprzedników πv. Ponieważ tutaj interesuje nas wiele drzew to łatwiej będzie nam używać macierzy poprzedników Π. Macierz tą definiujemy używając funkcji πv w następujący sposób:


Πv,u=πv(u).


W pozostałej części tego wykładu zajmiemy się tylko wyznaczaniem macierzy odległości D. Jak to zostało pokazane w Zadaniu 3 do poprzedniego wykładu znając odległości w grafie drzewo najkrótszych ścieżek można wyznaczyć w czasie O(|E|), a więc |V| drzew możemy wyliczyć w czasie O(|E||V|). Czas ten jest mniejszy niż czas działania wszystkich prezentowanych w tym wykładzie algorytmów, więc bez straty ogólności, a zyskując na prostocie prezentacji możemy ograniczyć się tylko do wyznaczenia macierzy odległości D.

Co więcej będziemy zakładać, że w grafie nie ma ujemnych cykli. Ujemne cykle można wykryć w czasie O(|V||E|) przy użyciu Algorytmu Bellmana-Forda. Zobacz Zadanie 4 do Wykładu 4.

Najkrótsze ścieżki i mnożenie macierzy

Załóżmy, że dane mamy dwie macierze wag C oraz D rozmiaru n×n. Dla macierzy tych definiujemy operację ×minl iloczynu odległości, której wynikiem jest także macierz rozmiaru n×n, zdefiniowana jako:

Parser nie mógł rozpoznać (błąd składni): {\displaystyle (C \times_{\min} D)_{i,j} = \min_{k = 1,\ldots,n} C_{i,k} + D_{k,j}. </center> }} {{wniosek|wniosek_konkatenacja|1|3= Jeżeli założymy, że <math>C} i D opisują minimalne wagi odpowiednio zbioru ścieżek odpowiednio ΠC i ΠD w pewnym grafie G, to iloczyn odległości wyznacza minimalne wagi zbioru ścieżek powstałego z konkatenacji ścieżek ze zbioru ΠC ze ścieżkami zbioru ΠD.      (1)


Pokażemy teraz, że produkt odległości jest operacją łączną.

Lemat io_łączny

Dla macierzy C, D i E

rozmiaru n×nzachodzi:


(C×minD)×minE=C×min(D×minE).

Dowód

Powyższa równość wynika wprost z wzoru (1)) oraz

przemienności operacji min.

Co więcej produkt odległości jest przemienny względem dodawania.

Lemat io_przemienny

Dla macierzy C, D

i E rozmiaru n×nzachodzi:


C×min(D+E)=C×minD+C×minE,


oraz


(D+E)×minC=D×minC+E×minC.

Dowód

Te dwie równości wynikają ponownie z

wzoru (1) oraz przemienności operacji min

względem dodawania.

Zdefiniujmy macierz

Imin

rozmiaru

n×n

jako:

(Imin)i,j={0,jeśli i=j,,jeśli ij.

Macierz ta jest jedynką dla iloczynu odległości.

Lemat io_jedynka

Dla macierzy C rozmiaru n×n zachodzi:


Imin×minC=C×minImin=C.

Szablon:Dowód


Łączność iloczynu odległości ma dla nas bardzo ważne konsekwencję i pozwoli nam na konstrukcję algorytmu obliczania odległości w grafie między wszystkimi parami wierzchołków działającego w czasie O(n3logn). Niech W będzie macierzą wag grafu G=(V,E). Rozważmy macierz Wm zdefiniowaną jako:


Parser nie mógł rozpoznać (nieznana funkcja „\begin{cases}”): {\displaystyle W^{m} = \begin{cases} I_{\min}, &\mbox{jeżeli } m=0,\\ W \times_{\min} W^{m-1}, &\mbox{jeżeli } m>0. }

Pokażemy teraz, że macierz Wm opisuje odległości między wierzchołkami grafu ale tylko dla ścieżek używających mniej niż m krawędzi.

Lemat potęgi_odległości

Element Wi,jm macierzy Wm zadaje

najmniejszą wagę ścieżki wychodzącej z wierzchołka i do wierzchołka j spośród ścieżek, które zawierają mniej niż m krawędzi, tzn.:


Parser nie mógł rozpoznać (nieznana funkcja „\mboc”): {\displaystyle w_{i,j}^{m} = \begin{cases} \min\{w(p): p \mbox{ ścieżka o długości } \le m \mboc{ z } u \mbox{ do } v\}, & \mbox{jeżeli istnieje ścieżka o długości } \le m \mboc{ z } u \mbox{ do } v,\\ \infty & \mbox{w przeciwnym przypadku.} \end{cases} }

Szablon:Dowód


Zajmiemy się teraz konstrukcją algorytmu obliczającego najkrótsze ścieżki w grafie. W tym celu będziemy potrzebowali jeszcze udowodnić następujące dwa lematy.

Lemat lemat_6

Jeżeli w grafie G=(V,E), w którym wagi krawędzi zadane

są macierzą W nie istnieje cykl o ujemnej wadze to:


δ(u,v)=Wu,v(k), dla kn1.

Szablon:Dowód

Zauważmy, że iloczyn odległości dwóch macierzy możemy policzyć w czasie O(|V|3) wykorzystując następujący algorytm.


Algorytm algorytm_iloczyn_odległości


 {{{3}}}

Ponieważ operacja iloczynu odległości jest łączna to możemy wykorzystać algorytm szybkiego potęgowania i policzyć odległości przy pomocy następującego algorytmu.

Algorytm algorytm_apsp_mnozenie


 ODLEGŁÓŚCI-I(W)
 1  D=W,
 2  k=1
 3 while n1>k do
 4   D=MNOŻENIE-ODLEGŁOŚCI(D,D)
 5   m=2m
 7  return D

Poprawności tego algorytmu wynika wprost z Lematu 6 ponieważ na zakończenie algorytmu D=Wm i m>n1.


Algorytm Floyda-Warshalla

W algorytmie Floyda-Warshalla wykorzystamy inną cechę najkrótszych ścieżek niż ta użyta w algorytmie z wykorzystaniem iloczynu odległości. W poprzednim algorytmie konstruowaliśmy coraz dłuższe ścieżki, natomiast tutaj będziemy konstruować ścieżki przechodzące przez coraz większy zbiór wierzchołków. Wierzchołkiem {{kotwica|wierzchołek_wewnetrzny|wewnetrznym} ścieżki p=(v0,,vl) jest każdy wierzchołek na ścieżce p różny od jej początku v0 i końca vl.

Niech zbiorem wierzchołków grafu G będzie V={1,,n}. Niech di,j(k) dla k=0,,n oznacza najmniejszą wagę ścieżki z i do j, spośród ścieżek których wierzchołki wewnętrzne należą do zbioru {v1,,vk. Pokażemy następujący rekurencyjny wzór na D(k).

Lemat lemat_7

Dla k=0,,n zachodzi:


di,j(k)={wi,j,jeżeli k=0,min(di,j(k1),di,k(k1)+dk,j(k1),jeżeli k1.


Szablon:Dowód

Wykorzystując wzór (2) możemy skonstruować następujący algorytm obliczający w czasie O(|V|3) odległości między wszystkimi parami wierzchołków.

Algorytm algorytm_Floyda-Warshalla


 między wszystkimi parami wierzchołków I
 ODLEGŁÓŚCI-II(W)
 1  D(0)=W,
 2  for k=1 to n do
 3    for i=1 to n do
 4      for j=1 to n do
 5        di,j(k)=min(di,j(k1),di,k(k1)+dk,j(k1))
 6  return D(n)