Zaawansowane algorytmy i struktury danych/Wykład 6: Różnice pomiędzy wersjami
Nie podano opisu zmian |
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 . Przedstawimy trzy algorytmu rozwiązujące ten problem:
- algorytm wykorzystujący mnożenie macierzy działający w czasie ,
- algorytm Floyda-Warshalla działający w czasie ,
- algorytm Johnsona działający w czasie .
== 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 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 , co daje nam algorytm rozwiązujący problem policzenia odległości między wszystkimi parami wierzchołków działający w czasie .
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 . 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 rozmiaru reprezentującą wagi krawędzi -wierzchołkowego grafu . Dla macierzy tej zachodzi:
W problemie najkrótszych ścieżek między wszystkimi parami
wierzchołków chcemy wyznaczyć macierz rozmiaru
taką, że jest równe
odległości z wierzchołka do
wierzchołka . Chcemy także wyznaczyć dla każdego
wierzchołka drzewo najkrótszych ścieżek
ukorzenione w . Podobnie jak w
poprzednim rozdziale drzewo możemy kodować dla
każdego wierzchołka przy pomocy funkcji poprzedników
. Ponieważ tutaj interesuje nas wiele drzew to
łatwiej będzie nam używać macierzy
poprzedników . Macierz tą definiujemy używając
funkcji w następujący sposób:
W pozostałej części tego wykładu zajmiemy się tylko wyznaczaniem
macierzy odległości . 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 , a więc drzew możemy
wyliczyć w czasie . 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
.
Co więcej będziemy zakładać, że w grafie nie ma ujemnych cykli. Ujemne cykle można wykryć w czasie 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 oraz rozmiaru . Dla macierzy tych definiujemy operację l iloczynu odległości, której wynikiem jest także macierz rozmiaru , 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 opisują minimalne wagi odpowiednio zbioru ścieżek odpowiednio i w pewnym grafie , to iloczyn odległości wyznacza minimalne wagi zbioru ścieżek powstałego z konkatenacji ścieżek ze zbioru ze ścieżkami zbioru . (1)
Pokażemy teraz, że produkt odległości jest operacją łączną.
Lemat io_łączny
rozmiaru zachodzi:
Dowód
Co więcej produkt odległości jest przemienny względem dodawania.
Lemat io_przemienny
i rozmiaru zachodzi:
oraz
Dowód
wzoru (1) oraz przemienności operacji
względem dodawania.
Zdefiniujmy macierz
rozmiaru
jako:
Macierz ta jest jedynką dla iloczynu odległości.
Lemat io_jedynka
Łą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
. Niech będzie
macierzą wag grafu . Rozważmy
macierz 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 opisuje odległości między wierzchołkami grafu ale tylko dla ścieżek używających mniej niż krawędzi.
Lemat potęgi_odległości
najmniejszą wagę ścieżki wychodzącej z wierzchołka do wierzchołka spośród ścieżek, które zawierają mniej niż krawędzi, tzn.:
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
są macierzą nie istnieje cykl o ujemnej wadze to:
Zauważmy, że iloczyn odległości dwóch macierzy możemy policzyć w czasie 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 , 2 3 while do 4 MNOŻENIE-ODLEGŁOŚCI 5 7 return
Poprawności tego algorytmu wynika wprost z Lematu 6 ponieważ na zakończenie algorytmu i .
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 jest każdy wierzchołek na ścieżce różny od jej początku i końca .
Niech zbiorem wierzchołków grafu będzie . Niech dla oznacza najmniejszą wagę ścieżki z do , spośród ścieżek których wierzchołki wewnętrzne należą do zbioru . Pokażemy następujący rekurencyjny wzór na .
Lemat lemat_7
Wykorzystując wzór (2) możemy skonstruować następujący algorytm obliczający w czasie 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 , 2 for to do 3 for to do 4 for to do 5 6 return