Alberi di copertura minimi 1
Problema Nella progettazione di circuiti elettronici è spesso necessario collegare i morsetti. Per connettere un insieme di n morsetti si può usare un insieme di n-1 fili elettrici. E preferibile adottare la soluzione che usa la minor quantità di filo elettrico. 2
Soluzione sia G = (V, E) un grafo non orientato e connesso, dove V è l insieme dei morsetti (vertici) ed E è l insieme dei collegamenti tra le coppie di morsetti (archi). Per ogni arco (u, v) si ha un peso w(u, v) che rappresenta la lunghezza del filo (costo) necessaria alla connessione di u e v. Si vuole trovare un sottoinsieme aciclico T E che connetta tutti i vertici del grafo e tale che venga minimizzato il peso totale: w(t) = Σ w (u, v) (u,v) T T è aciclico e collega tutti i vertici. T è un albero di copertura minimo. 3
Esempio di albero di copertura minimo 4 b 8 7 2 c d 9 a 11 i 4 14 e 8 7 6 10 h 1 g 2 f Gli archi in neretto costituiscono l albero di copertura minimo. Esso non è unico (questo mostra che si può usare la strategia greedy ). Individuarne un altro. Quanto è il peso totale? 4
Costruzione di un albero di copertura minimo Algoritmo generico per trovare un albero di copertura minimo per un grafo G(V, E). Ad ogni passo viene determinato un arco sicuro (u, v) t.c. A (u, v) è ancora un sottoinsieme di albero di copertura minimo. GENERIC-MST(G, w){ A= ; while (A non è un albero di copertura){ trova (u, v) sicuro per A; A = A {(u, v)}; } return A; } 5
Definizioni Un taglio (S, V-S) di un grafo non orientato G = (V, E) è una partizione di V. Un arco (u, v) E attraversa il taglio (S, V-S) se uno dei suoi estremi è in S e l altro è in V-S. Un taglio rispetta un insieme A di archi se nessun arco di A attraversa il taglio. Un arco che attraversa un taglio è leggero se il suo peso è minimo tra i pesi degli archi che attraversano quel taglio (vi possono essere più archi leggeri). 6
Esempio 4 b 8 7 2 c d 9 a 11 i 4 14 e S -S 8 h 7 1 6 g 2 f 10 S V-S 7
Teorema (per trovare un arco sicuro) Un arco (u, v) è sicuro se può essere aggiunto ad un albero di copertura minimo A lasciandolo tale. Sia G =(V, E) un grafo non orientato e connesso. Sia A un sottoinsieme di E contenuto in un qualche albero di copertura minimo per G; sia (S, V-S) un taglio che rispetta A, e sia (u, v) un arco leggero che che attraversa (S, V-S). Allora (u, v) è sicuro per A. 8
Corollario Sia G =(V, E) un grafo non orientato e connesso. Sia A un sottoinsieme di E contenuto in un albero di copertura minimo per G, e sia C una componente connessa (albero) nella foresta G A =(V, A). Se (u, v) è un arco leggero che connette C a qualche altra componente G A, allora (u, v) è sicuro per A. 9
Esercizi 1. Sia (u, v) un arco di peso minimo in un grafo G. si dimostri che (u, v) appartiene ad un albero di copertura minimo G. 2. Si mostri che se un arco (u, v) è contenuto in un qualche albero di copertura minimo, allora esso è un arco leggero che attraversa un taglio del grafo. 3. Si mostri che un grafo ha un unico albero di copertura minimo se per ogni taglio del grafo esiste un unico arco leggero che attraversa il taglio. 10
Algoritmo di Kruskal (I) ST-KRUSKAL(G, w){ A= ; for (ogni vertice v V[G]) MAKE-SET(V); ordina gli archi di E per peso w non decrescente for (ogni arco (u, v) E, in ordine di peso non decrescente){ if (FIND-SET(u)!=FIND-SET(v)){ A = A {(u, v)}; UNION(u, v); } } return A; 11
Algoritmo di Kruskal (II) Il tempo di esecuzione per un grafo G = (V, E) dipende dalla realizzazione della struttura di dati per gli insiemi disgiunti. L inizializzazione richiede un tempo O(V), ed il tempo necessario per ordinare gli archi è E*(lg E). Ci sono O(E) operazioni sulla foresta di insiemi disgiunti. Il tempo di esecuzione totale dell algoritmo di Kruskal è O(E*lg E). 12
Algoritmo di Prim (I) MST-PRIM(G, w, r){ Q=V[G]; for (ogni u Q) key[u] = INF; key[r]=0; p[r]=null; while (Q!= ){ u=extract-min(q); for (ogni v Adj[u]){ if (v Q && w(u, v) < key[v]) p[v]=u; key[v]=w(u, v); } } } In tutto l algoritmo l insieme V- contiene tutti i vertici dell albero copertura minimo che si s costruend 13
Algoritmo di Prim (II) L efficienza dell algoritmo dipende da come viene realizzata la coda con priorità Q. Il tempo totale richiesto dall algoritmo di Prim è O(V*lg V + E*lgV) = O(E*lg V). Il tempo di esecuzione dell algoritmo può essere differente utilizzando uno heap di Fibonacci (O(E+V*lgV)), anziché uno heap binario (O(E*lg V)). 14
15