Dijkstrin algoritam — najkraći putevi u grafu
Dijkstrin algoritam pronalazi najkraće rastojanje od jednog početnog čvora do svih ostalih čvorova u grafu. Radi ispravno samo ako su sve težine grana nenegativne.
Ovo je jedan od najvažnijih algoritama u grafovima i spada u greedy algoritme. Na svakom koraku bira čvor sa najmanjom trenutno poznatom udaljenošću i "zapečati" njegov rezultat.
Kada koristiti Dijkstru?
Algoritam se koristi kada:
- graf ima težine (dužine, vreme, cena...)
- sve težine su nenegativne
- želimo najkraći put od polaznog do svih ostalih čvorova
Primeri:
- navigacija (GPS)
- video igre
- mreže i rutiranje
- lavirinti
Ideja algoritma
Za svaki čvor čuvamo udaljenost od starta. Početno stanje:
- start = 0
- ostali = ∞
Na svakom koraku:
- biramo najbliži neobrađen čvor
- radimo relaksaciju suseda
- ponavljamo
Relaksacija:
ako je dist[u] + w(u,v) < dist[v]:
ažuriraj dist[v]
Implementacija (C++) — priority_queue
// uključuje sve standardne biblioteke
#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
// graf: lista suseda (čvor, težina)
vector<pair<int,int>> graf[100];
// niz udaljenosti
vector<int> d;
void dijkstra(int start, int n){
// inicijalizacija
d.assign(n+1, INF);
d[start] = 0;
// min-heap (udaljenost, čvor)
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
pq.push({0, start});
while(!pq.empty()){
auto [dist, v] = pq.top();
pq.pop();
// ako je zastareo unos - preskoči
if(dist > d[v]) continue;
// prolazak kroz susede
for(auto [sused, w] : graf[v]){
if(d[v] + w < d[sused]){
d[sused] = d[v] + w;
pq.push({d[sused], sused});
}
}
}
}
Korišćenje
int main(){
int n = 5;
// dodavanje grana
graf[1].push_back({2, 7});
graf[1].push_back({3, 9});
graf[2].push_back({4, 10});
graf[3].push_back({4, 2});
graf[4].push_back({5, 1});
dijkstra(1, n);
for(int i = 1; i <= n; i++)
cout << "distanca do " << i << " = " << d[i] << endl;
}
Rekonstrukcija najkraćeg puta
vector<int> parent;
void dijkstra(int start, int n){
d.assign(n+1, INF);
parent.assign(n+1, -1);
d[start] = 0;
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
pq.push({0, start});
while(!pq.empty()){
auto [dist, v] = pq.top();
pq.pop();
if(dist > d[v]) continue;
for(auto [sused, w] : graf[v]){
if(d[v] + w < d[sused]){
d[sused] = d[v] + w;
parent[sused] = v; // čuvamo prethodnika
pq.push({d[sused], sused});
}
}
}
}
// vraća put od starta do cilja
vector<int> rekonstruiši_put(int cilj){
vector<int> put;
for(int v = cilj; v != -1; v = parent[v])
put.push_back(v);
reverse(put.begin(), put.end());
return put;
}
Greške koje treba izbegavati
- Negativne težine → koristi Bellman-Ford
- Ne prekidati prerano (osim ako tražiš jedan cilj uz optimizaciju)
- Obavezna provera:
if(dist > d[v]) continue;
Složenost algoritma
| Struktura | Složenost |
|---|---|
| Heap | O((V + E) log V) |
| Matrica | O(V²) |
Dijkstrin algoritam — najkraći putevi u grafu
Dijkstrin algoritam pronalazi najkraće rastojanje od jednog početnog čvora do svih ostalih čvorova u grafu. Radi ispravno samo ako su sve težine grana nenegativne.
Ovo je jedan od najvažnijih algoritama u grafovima i spada u greedy algoritme. Na svakom koraku bira čvor sa najmanjom trenutno poznatom udaljenošću i "zapečati" njegov rezultat.
Kada koristiti Dijkstru?
Algoritam koristi se kada:
- graf ima težine (dužine, vreme, cena...)
- sve težine su nenegativne
- želimo najkraći put od polaznog do svih ostalih čvorova
Primeri:
- navigacija na mapi (Google Maps, GPS)
- najbrži način da pređemo nivo u video igri
- optimizacija mreža i protoka podataka
- najkraća ruta kroz maze/lavirint
Ideja algoritma
Za svaki čvor čuvamo udaljenost od starta. Na početku, udaljenost startnog čvora je 0, a svih ostalih je beskonačno (∞).
Na svakom koraku:
- izaberemo neobrađen čvor sa najmanjom udaljenošću (greedy korak)
- pokušamo da relaksiramo (poboljšamo) susedne čvorove
- ponavljamo dok ne obradimo sve čvorove
Relaksacija:
ako je dist[u] + w(u,v) < dist[v]:
onda ažuriraj dist[v]
Implementacija (C++) — verzija sa priority_queue
Najbolja i najčešća implementacija koristi prioritetni red (min-heap).
#include
using namespace std;
const int INF = 1e9;
vector> graf[100];
// graf[x] = lista parova (sused, težina)
vector d; // udaljenosti
void dijkstra(int start, int n){
d.assign(n+1, INF);
d[start] = 0;
priority_queue, vector>, greater>> pq;
pq.push({0, start}); // (udaljenost, čvor)
while(!pq.empty()){
auto [dist, v] = pq.top();
pq.pop();
if(dist > d[v]) continue; // preskačemo ako nije aktuelno
for(auto [sused, w] : graf[v]){
if(d[v] + w < d[sused]){
d[sused] = d[v] + w;
pq.push({d[sused], sused});
}
}
}
}
Korišćenje:
int main(){
int n = 5; // broj čvorova
// dodavanje grana (u, v, tezina)
graf[1].push_back({2, 7});
graf[1].push_back({3, 9});
graf[2].push_back({4, 10});
graf[3].push_back({4, 2});
graf[4].push_back({5, 1});
dijkstra(1, n);
for(int i=1; i<=n; i++)
cout << "distanca do " << i << " = " << d[i] << endl;
}
Rekonstrukcija najkraćeg puta
Da bismo znali konkretan put, čuvamo prethodnika (parent) svakog čvora.
// dodati uz postojeći kod
vector parent;
void dijkstra(int start, int n){
d.assign(n+1, INF);
parent.assign(n+1, -1);
d[start] = 0;
priority_queue, vector>, greater>> pq;
pq.push({0, start});
while(!pq.empty()){
auto [dist, v] = pq.top();
pq.pop();
if(dist > d[v]) continue;
for(auto [sused, w] : graf[v]){
if(d[v] + w < d[sused]){
d[sused] = d[v] + w;
parent[sused] = v; // pamti putanju
pq.push({d[sused], sused});
}
}
}
}
// funkcija za vraćanje puta
vector rekonstruiši_put(int cilj){
vector put;
for(int v = cilj; v != -1; v = parent[v])
put.push_back(v);
reverse(put.begin(), put.end());
return put;
}
// primer poziva
auto put = rekonstruiši_put(5);
for(int x : put) cout << x << " ";
Vizuelni primer
Graf:
1 →2 (7), 1→3 (9), 3→4 (2), 4→5 (1), 2→4 (10)
Izvor: 1
Najkraći put 1 → 3 → 4 → 5 = 12
Greške koje treba izbegavati
- Ne sme biti **negativnih težina** (onda se koristi Bellman-Ford).
- Ne sme se završiti kada se pusti cilj — Dijkstra ide dok se svi ne obrade.
- Ne porediti nova rastojanja bez provere `if(dist > d[v]) continue;`.
Složenost algoritma
| Struktura | Složenost |
|---|---|
| Prioritetni red (heap) | O((V + E) log V) |
| Matrična reprezentacija | O(V²) |
Vežba
Za vežbu, probaj da:
- Pronađeš najkraći put u mreži gradova (kao GPS)
- Napraviš program koji vraća sve čvorove na rastojanju ≤ K
- Implementiraš obrnuti algoritam: traženje najdaljeg čvora
Sledeća preporučena lekcija
□ Nastavljamo sa minimalnim razapinjućim stablima:
Bellman-Ford i Floyd-Warshall algoritmi