Minimo
Minimizza la somma dei pesi. Un vertice irraggiungibile ha distanza +∞. Un ciclo negativo raggiungibile può far scendere il costo senza limite per i vertici raggiungibili dal ciclo.
Algoritmi · Grafi pesati
Il percorso con meno archi non è sempre quello di peso minore. Le ipotesi sui pesi e sui cicli determinano sia l’algoritmo corretto sia l’esistenza di una risposta finita.
Per le nozioni di grafo, arco e visita, vedi Grafi: BFS e DFS.
In un grafo orientato e pesato G = (V, E), il peso di un cammino è la somma dei pesi dei suoi archi. Fissata una sorgente s, vogliamo conoscere il peso migliore per ogni vertice raggiungibile v e, tramite i predecessori, ricostruire un cammino che lo realizza.
Minimizza la somma dei pesi. Un vertice irraggiungibile ha distanza +∞. Un ciclo negativo raggiungibile può far scendere il costo senza limite per i vertici raggiungibili dal ciclo.
Massimizza la somma dei pesi. Nei DAG esiste una soluzione finita per ogni vertice raggiungibile. Se si ammettono passeggiate che ripetono vertici, un ciclo positivo utilizzabile può far crescere il peso senza limite.
Manteniamo una stima d[v] del costo minimo da s a v: d[s] = 0 e d[v] = +∞ per gli altri vertici. Se un cammino già noto verso u seguito dall’arco u → v migliora la stima di v, aggiorniamo distanza e predecessore.
Aggiorniamo anche prev[v] = u. Per ricostruire il percorso verso t, risaliamo i predecessori da t fino a s e invertiamo la sequenza. Se d[t] = +∞, t non è raggiungibile.
Dijkstra sceglie ogni volta il vertice non ancora definitivo con la stima minore, poi rilassa i suoi archi uscenti. Tutti gli archi raggiungibili devono avere peso ≥ 0: altrimenti un percorso scoperto più tardi potrebbe migliorare un vertice già estratto.
d[s] = 0; ogni altro d[v] = +∞; prev[v] = indefinito
inserisci (0, s) nella coda di priorità minima
finché la coda non è vuota:
estrai (costo, u)
se costo ≠ d[u]: continua // voce superata
per ogni arco u → v di peso w:
se d[u] + w < d[v]:
d[v] = d[u] + w; prev[v] = u
inserisci (d[v], v)
Esempio: s → a (4), s → b (1), b → a (2), a → t (1), b → t (7). L’ordine delle estrazioni valide è s, b, a, t. Da s otteniamo a = 4 e b = 1; da b miglioriamo a a 3 e troviamo t = 8; da a miglioriamo t a 4.
| Vertice | s | a | b | t |
|---|---|---|---|---|
| d | 0 | 3 | 1 | 4 |
| prev | — | b | s | a |
Il cammino minimo verso t è s → b → a → t e pesa 1 + 2 + 1 = 4. La scelta greedy è sicura perché aggiungere archi non negativi non può creare un percorso futuro più economico verso un vertice già estratto.
Bellman–Ford rilassa tutti gli archi per |V| − 1 passate. Dopo la passata k, le stime sono ottime per i cammini che usano al massimo k archi. Un cammino semplice ha al massimo |V| − 1 archi; perciò queste passate bastano se non esistono cicli negativi raggiungibili.
d[s] = 0; ogni altro d[v] = +∞
ripeti |V| − 1 volte:
per ogni arco u → v di peso w:
se d[u] è finito e d[u] + w < d[v]:
d[v] = d[u] + w; prev[v] = u
se nessuna stima è cambiata: termina le passate
per ogni arco u → v di peso w:
se d[u] è finito e d[u] + w < d[v]:
segnala un ciclo negativo raggiungibile
Esempio con un arco negativo: s → a (4), s → b (5), a → t (2), b → t (6), b → a (−3). Scorrendo gli archi in quest’ordine, la prima passata dà a = 2 e t = 6; la seconda migliora t a 4. Il risultato è s → b → a → t, peso 5 − 3 + 2 = 4. La versione di Dijkstra che rende definitivi i vertici estratti fisserebbe a al costo 4 troppo presto.
| Passata | s | a | b | t |
|---|---|---|---|---|
| 0 | 0 | ∞ | ∞ | ∞ |
| 1 | 0 | 2 | 5 | 6 |
| 2 | 0 | 2 | 5 | 4 |
| 3 | 0 | 2 | 5 | 4 |
Per esempio, s → a (1), a → b (−2), b → a (1), b → t (2): a → b → a pesa −1. Ripetendolo prima di arrivare a t, il costo verso a, b e t scende senza limite.
In un DAG (grafo orientato aciclico) ogni cammino è semplice. Calcoliamo un ordinamento topologico, poniamo L[s] = 0 e L[v] = −∞ per gli altri vertici, poi percorriamo i vertici in tale ordine. Per ogni arco u → v aggiorniamo L[v] = max(L[v], L[u] + w(u,v)) se L[u] è finito. Salviamo il predecessore quando miglioriamo la stima.
Funziona anche con pesi negativi: l’assenza di cicli è la condizione essenziale. Nello stesso DAG, sostituire max con min e −∞ con +∞ calcola i cammini minimi in O(|V| + |E|).
| Ordine | s | a | b | t |
|---|---|---|---|---|
| L | 0 | 3 | 7 | 12 |
| prev | — | s | a | b |
Il cammino massimo è s → a → b → t, peso 3 + 4 + 5 = 12. Su grafi generali, cambiare segno ai pesi e applicare Bellman–Ford risolve la variante con passeggiate solo se non ci sono cicli positivi raggiungibili; non risolve il problema del cammino semplice massimo, che in generale è NP-difficile.
| Obiettivo e ipotesi | Metodo | Tempo |
|---|---|---|
| Minimo, tutti gli archi di peso 1 | BFS | O(|V| + |E|) |
| Minimo, DAG anche con pesi negativi | Ordine topologico + min | O(|V| + |E|) |
| Minimo, pesi non negativi | Dijkstra | O((|V| + |E|) log |V|) |
| Minimo, possibili pesi negativi | Bellman–Ford | O(|V| + |V|·|E|) |
| Massimo, DAG | Ordine topologico + max | O(|V| + |E|) |
I limiti usano liste di adiacenza e grafi semplici; per Dijkstra assumono una coda di priorità binaria. I tempi includono i vertici anche se il grafo è disconnesso. Bellman–Ford può terminare prima quando una passata non cambia nulla, ma il caso peggiore resta O(|V| + |V|·|E|).
Un albero ricoprente minimo collega tutti i vertici spendendo il meno possibile sull’intera rete; non garantisce i cammini più brevi da s. Vedi minimum spanning tree.
s → b → a → t, peso 4. Il cammino con due archi s → a → t pesa 5.
No. Il controllo finale richiede d[u] finito; le distanze da s restano corrette nella parte raggiungibile.
Minimo: s → t, peso 1. Massimo: s → a → t, peso −2 + 4 = 2. L’ordine topologico s, a, t consente entrambi i calcoli.
No. Il ciclo deve essere percorribile lungo una passeggiata che arriva a t. Può rendere illimitati i valori di altri vertici, ma non quello di t.
Vuoi conoscere le distanze fra ogni coppia di vertici? Prosegui con Johnson e Floyd–Warshall.