Minimum spanning tree
In questa pagina 5
Nota sulle fonti: l'argomento è nel programma ufficiale ma non nel materiale del corso consultato; la nota è scritta dal programma con conoscenze standard.
Dato un grafo non diretto, pesato e connesso, un minimum spanning tree (MST, albero di copertura di peso minimo) è uno spanning tree (vedi Grafi - definizioni e proprietàGrafo G=(V,E) diretto e non diretto, grafo semplice e pesato; incidenza, adiacenza, grado; cammini, cicli, sottografi, grafi connessi e componenti connesse; alberi liberi, foreste, spanning tree e spanning forest; proprietà con dimostrazioni (somma dei gradi = 2m, m <= n(n-1)/2, alberi m = n-1, connessi m >= n-1, foreste m <= n-1).Grafi - definizioni e proprietà →) che minimizza il peso totale . Ha archi. Applicazione tipica: collegare tutti i nodi di una rete (cavi, broadcast efficiente) con il costo minimo. Se i pesi sono tutti distinti l'MST è unico; altrimenti ce ne può essere più d'uno.
Proprietà del taglio
Un taglio è una partizione con non vuoti; un arco lo attraversa se ha un estremo in e uno in .
Proprietà del taglio. Sia un sottoinsieme degli archi di un qualche MST e sia un taglio che nessun arco di attraversa. Se è un arco di peso minimo tra quelli che attraversano il taglio, allora è ancora contenuto in un MST.
Dimostrazione. Sia un MST che contiene . Se non c'è nulla da dimostrare. Altrimenti contiene un ciclo; questo attraversa il taglio in un altro arco (un ciclo attraversa un taglio un numero pari di volte, quindi almeno due), con per la minimalità di . è uno spanning tree (connesso, archi) con , quindi è un MST; contiene perché (nessun arco di attraversa il taglio) e contiene .
Entrambi gli algoritmi sono greedy: a ogni passo aggiungono un arco "sicuro" in base alla proprietà del taglio.
Algoritmo di Kruskal
Si scorrono gli archi per peso crescente e si aggiunge l'arco se non crea un ciclo con quelli già scelti, cioè se collega due componenti diverse.
Algoritmo Kruskal(G)
ordina E per peso crescente
ogni vertice forma una componente da solo
T <- insieme vuoto
for each e = (u, v) in E nell'ordine do
if componente(u) != componente(v) then
T <- T + {e}; fondi le due componenti
return TIl taglio della proprietà è, a ogni passo, una componente contro il resto: l'arco minimo tra componenti diverse è sicuro. Con una struttura union-find (partizioni con find e union) l'ordinamento costa (perché ) e le operazioni sulle componenti sono quasi costanti: totale .
Algoritmo di Prim
Si parte da un vertice e si fa crescere un unico albero, aggiungendo sempre l'arco di peso minimo che collega l'albero a un vertice esterno. Si realizza come Dijkstra (vedi Cammini minimi e algoritmo di DijkstraGrafi pesati, lunghezza di un cammino e distanza; sottocammini di un cammino minimo; problema SSSP; algoritmo di Dijkstra con cloud e priority queue, rilassamento degli archi, esempio svolto; correttezza (due lemmi) e complessità O(min(n^2, (n+m) log n)) con lista non ordinata o heap; pesi non negativi.Cammini minimi e algoritmo di Dijkstra →) con una coda con priorità in cui la chiave di un vertice esterno è il peso del miglior arco che lo collega all'albero.
Algoritmo Prim(G, s)
forall v in V do v.D <- +infinito; v.parent <- null
s.D <- 0
Q <- coda con priorità con tutti i vertici (chiave v.D)
while Q non è vuota do
u <- Q.removeMin() (u entra nell'albero, insieme all'arco (u.parent, u))
forall (u, v) in E con v in Q do
if w(u, v) < v.D then v.D <- w(u, v); v.parent <- u; aggiorna QLa differenza con Dijkstra è nella regola di rilassamento: qui v.D <- w(u,v), non u.D + w(u,v). Gli archi (v.parent, v) formano l'MST. Complessità: come Dijkstra, con heap e con lista non ordinata.
Esempio svolto
Kruskal. Archi ordinati: , , , , , , , , . Si aggiungono (componenti ), (), (), (fonde in ), (fonde tutto: , 5 archi: fine); , , , sarebbero scartati perché creano cicli. Peso totale .
Prim da . Si aggiungono nell'ordine , , , , : stesso albero, peso . (Verificato con un'implementazione in Python di entrambi.)
Attenzione: l'MST non coincide con l'albero dei cammini minimi di Dijkstra da (lì ha parent con l'arco , qui l'arco è ): minimizzano grandezze diverse (peso totale contro distanze dalla sorgente).
Errori comuni
- Confondere MST e albero dei cammini minimi: obiettivi diversi.
- In Prim usare
u.D + w(u,v)(è Dijkstra). - In Kruskal controllare solo che l'arco non sia già in invece di verificare che non crei un ciclo.
- Applicare MST a grafi non connessi senza ottenere una foresta di copertura (un MST per componente).
Versione ripasso
- MST: spanning tree di peso totale minimo in connesso, archi; unico se i pesi sono distinti (vedi Grafi - definizioni e proprietàGrafo G=(V,E) diretto e non diretto, grafo semplice e pesato; incidenza, adiacenza, grado; cammini, cicli, sottografi, grafi connessi e componenti connesse; alberi liberi, foreste, spanning tree e spanning forest; proprietà con dimostrazioni (somma dei gradi = 2m, m <= n(n-1)/2, alberi m = n-1, connessi m >= n-1, foreste m <= n-1).Grafi - definizioni e proprietà →).
- Proprietà del taglio: se MST e è un taglio non attraversato da , l'arco minimo che lo attraversa può essere aggiunto: qualche MST. Prova: in il ciclo attraversa il taglio in un altro arco con ; non pesa di più.
- Kruskal: archi per peso crescente, aggiunge se collega due componenti diverse (union-find); .
- Prim: un solo albero che cresce da ; come Dijkstra ma con
v.D <- w(u,v); con heap, con lista (vedi Cammini minimi e algoritmo di DijkstraGrafi pesati, lunghezza di un cammino e distanza; sottocammini di un cammino minimo; problema SSSP; algoritmo di Dijkstra con cloud e priority queue, rilassamento degli archi, esempio svolto; correttezza (due lemmi) e complessità O(min(n^2, (n+m) log n)) con lista non ordinata o heap; pesi non negativi.Cammini minimi e algoritmo di Dijkstra →). - Esempio (grafo di Dijkstra): archi scelti , , , , , peso ; non è l'albero dei cammini minimi da .
- Kruskal:
ordina E per peso crescente; per ogni : secomponente(u) != componente(v)aggiungi e fondi le componenti. Prim: come Dijkstra conv.D <- w(u,v)(peso del miglior arco verso l'albero). - Esempio: archi di peso () ⇒ MST di peso ; , , , scartati.
- Errori: MST contro cammini minimi;
u.D + win Prim; ciclo non controllato in Kruskal.