Sunteți pe pagina 1din 25

JOHNSON'S ALGORITHM

• Algoritmul lui Johnson este o modalitate de a gasi drumurile


minime dintre toate perechile de varfuri intr-un grafic
directionat, ponderat.
• Algoritmul lui Johnson functioneaza pe greutati negative, dar
nu pe ciclii cu greutati negative.
• Pentru grafuri rare
DEFINITIE
• Folosește liste de adiacență
CARACTERISTICI
• Bazat pe Dijkstra și Bellman-Ford
• ! Drumul minim sau costul nu se refera la lungime, ci la o
greutate, o masura, o cantitate.
“ Cel mai eficient algoritm pentru o rețea nodulara este
acela al drumurilor minime


n. 16 decembrie 1933 - d. 10 septembrie 1994
DONALD B. JOHNSON
DONALD B. JOHNSON

• computer scientist american, reasearcher in designul si analiza algoritmica si fondatorul


departamentului de ‘Computer Science’ in cadrul Dartmouth College
• a creat d-ary heap sau d-heap ca priority queue data structure (= o generalizare a heapului binar in care
nodurile au d heapuri, in loc de 2 ) in 1975
• a publicat tehnica pentru prima oara in 1977
DESCRIEREA ALGORITMULUI
Algoritmul lui Johnson permite transformarea unui graf cu muchii negative (dar fără cicluri negative) într-un
graf echivalent fără muchii negative. Acest lucru este util deoarece calcularea distanțelor poate fi mai rapidă
atunci când nu exista muchii negative.
• Pasul 1. Se introduce un nod virtual conectat cu toate celelalte noduri printr-o muchie de cost 0 (zero).
• Pasul 2. Se calculează vectorul de distanțe între nodul virtual și toate celelalte noduri. Observație: acest
vector v-a contine doar elemente mai mici sau egale cu zero din cauza muchiei de cost zero.
• Pasul 3. Pentru a crea graful echivalent, modificăm costurile tuturor muchiilor din graful inițial conform
formulei: cost'(a, b) = cost(a, b) + Dist[a] - Dist[b]
• Pasul 4. Calculăm distanțele dintre nodurile dorite folosind algoritmul lui Dijkstra pe graful modificat
• Pasul 5. Pentru a transforma o distanță pe graful modificat într-o distanță pe graful inițial folosim formula:
dist(a, b) = dist'(a, b) - Dist[a] + Dist[b]
IMPLEMENTAREA ALGORITMULUI

Algoritmul se poate implementa în două moduri:


• Folosind matricea ponderilor 
• Folosind liste de adiacență
SIMULAREA ALGORITMULUI PE UN GRAF DAT
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist 0 0 0 0

Vom calcula vectorul de distanțe folosind algoritmul Bellman-


Ford.
Introducem toate nodurile într-o coadă și inițializăm toate
distanțele cu 0, deoarece toate nodurile sunt conectate cu
"nodul virtual" printr-o muchie de cost 0 (zero).
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist 0 0 0 0

În coadă avem nodurile [x, y, z, w].


Alegem nodul x. Acesta nu produce nicio modificare. Îl
eliminăm din coadă.
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist 0 0 0 0

În coadă avem nodurile [y, z, w].


Alegem nodul y. Acesta nu produce nicio modificare. Îl
eliminăm din coadă.
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist -7 0 0 0

În coadă avem nodurile [z, w].


Alegem nodul z. Acesta modifică distanța lui x. Îl eliminăm din
coadă pe z și îl introducem pe x.
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist -7 0 0 0

În coadă avem nodurile [w, x].


Alegem nodul w. Acesta nu produce nicio modificare. Îl
eliminăm din coadă.
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist -7 -4 0 -1

În coadă avem nodurile [x].


Alegem nodul x. Acesta modifică distanțele lui y și w. Îl
eliminăm din coadă pe x și îi introducem pe y și w.
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist -7 -4 0 -1

În coadă avem nodurile [y, w].


Alegem nodul y. Acesta nu produce nicio modificare. Îl
eliminăm din coadă.
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist -7 -4 0 -1

În coadă avem nodurile [w].


Alegem nodul w. Acesta nu produce nicio modificare. Îl
eliminăm din coadă.
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist -7 -4 0 -1

Coada este goala, putem continua cu actualizarea muchiilor.


SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w Actualizăm fiecare muchie conform formulei:
Dist -7 -4 0 -1 cost'(a, b) = cost(a, b) + Dist[a] - Dist[b]
SIMULAREA ALGORITMULUI PE UN GRAF DAT
Nod x y z w

Dist -7 -4 0 -1

Vom analiza drumul z-x-w.


Pe graful final avem dist'(z, w) = 0 + 0 = 0.
Conform formulei, pe graful initial avem
dist(z, w) = dist'(z, w) - Dist[z] + Dist[w] = 0 - 0 + (-1) = -1.
Acest lucru se verifică deoarece pe e graful inițial avem
dist(z, w) = -7 + 6 = -1.
DEMONSTRATIA CORECTITUDINII
Vom pleca de la premisa că cost'(a, b) = cost(a, b) + Dist[a] - Dist[b].
Fie (u1u2u3 ... uk) drumul cel mai scurt între nodurile u1 și uk pe graful modificat astfel încât
dist'(u1,uk) = cost'(u1,u2) + cost'(u2,u3) + ... + cost'(uk-1,uk) = minim.

cost'(u1,u2) = cost(u1,u2) + Dist[u1] - Dist[u2]


cost'(u2,u3) = cost(u2,u3) + Dist[u2] - Dist[u3]
cost'(u3,u4) = cost(u3,u4) + Dist[u3] - Dist[u4]
....................................................................
cost'(uk-1,uk) = cost(uk-1,uk) + Dist[uk-1] - Dist[uk]
—————————————————————————————— (+)

cost'(u1,u2) + cost'(u2,u3) + ... + cost'(uk-1,uk) = cost(u1,u2) + cost(u2,u3) + ... + cost(uk-1,uk) + Dist[u1] - Dist[uk]

Dar Dist[u1] - Dist[uk] nu diferă în funcție de drum. => dacă (u1u2u3 ... uk) este cel mai scurt drum între
nodurile u1 și uk pe graful modificat, atunci va fi cel mai scurt drum si pe graful initial.
ALGORITMUL LUI JOHNSON ÎN VIAȚA REALĂ

• gasirea unor zboruri necesare cu cost minim, ale unor indivizi aflati in tari diferite (costul=pretul)
• alegerea celui mai avantajos drum, pentru a castiga o cursa (in care participatii pleaca din pozitii
distincte) (costul=timpul)
• folosit pentru algoritmii ce ruleaza pe echipamentele de retea, pentru a determina drumul minim de la
acesta la celelalte echipamente de retea (costul=timpul)
COMPLEXITATE ȘI OPTIMIZĂRI

• Complexitate implementare cu matrice de adiacență: O(N2) memorie, O(N3) timp


• Complexitate implementare cu liste de adiacență: O(N + M) memorie, O(N*M) timp
• Folosind o structura de date precum un HEAP, putem optimiza timpul segmentului care folosește
algoritmul Disjkstra la O(MlogN) pentru fiecare nod din care calculăm distanțele.
ROY-FLOYD

Vom rezolva urmatoarea problemă în două moduri:


Se dă un graf, să se calculeze distanțele dintre 
fiecare pereche de noduri.

Prima soluție folosește algoritmul Roy-Floyd.


(Soluția clasică)
Complexitate timp: O(N3)
Complexitatea spatiu: O(N2)
BELLMAN-FORD din fiecare nod
#include <iostream> queue<int> q; if (ADIA) {
#include <fstream> q.push(s); for (int i = 1; i <= n; i++)
#include <queue> while (q.size()) { for (int j = 1; j <= n; j++) {
int i = q.front(); int x;
using namespace std; q.pop(); cin >> x;
if (x)
Soluția cu algoritmul Bellam-Ford. const int MAX_N = 2001; if (++viz[i] > n) { edges[i].push_back({x, j});
typedef pair<int, int> Edge; cout << "Cicluri negative!"; }
Complexitate timp: O(MN2) exit(0); } else {
vector<Edge> edges[MAX_N]; } int m, a, b, c;
Complexitatea spatiu: O(N + M) cin >> m;
const bool ADIA = true; for (Edge e : edges[i]) { for (int i = 0; i < m; i++) {
if (dist[e.second] > dist[i] + e.first) { cin >> a >> b >> c;
int n; dist[e.second] = dist[i] + e.first; edges[a].push_back({c, b});
q.push(e.second); }
Observăm că această soluție are int dist[MAX_N]; } }
complexitatea teoretică cea mai mai. }
int viz[MAX_N]; } for (int i = 1; i <= n; i++) {
} bellman(i, dist);
void bellman(int s, int* dist) { for (int j = 1; j <= n; j++)
for (int i = 1; i <= n; i++) { int main() { cout << dist[j] << ' ';
dist[i] = 1e9; ifstream cin("royfloyd.in"); cout << endl;
viz[i] = 0; ofstream cout("royfloyd.out"); }
}
dist[s] = 0; cin >> n; return 0;
}
JOHNSON'S ALGORITHM PE GRAFURI RARE

Soluția cu algoritmul lui Johnson.


Complexitate timp: O(MN + N*MlogM)
Complexitatea spatiu: O(N + M)

Observăm că solutia aceasta este mai


Rapida pe grafuri rare.
JOHNSON'S ALGORITHM PE GRAFURI RARE

Soluția cu algoritmul lui Johnson.


Complexitate timp: O(MN + N*MlogM)
Complexitatea spatiu: O(N + M)

Observăm că solutia aceasta este mai


Rapida pe grafuri rare.

S-ar putea să vă placă și