Visite in Grafi BFS e DFS
Transcript
Visite in Grafi BFS e DFS
Visite in Grafi BFS e DFS Visita di un Grafo Obiettivo: Visitare una sola volta tutti i nodi del grafo. Es.: visitare un porzione del grafo del Web Difficoltà: Presenza di cicli: • Marcare i nodi visitati Presenza di nodi isolati: • La visita termina quando sono state considerate tutte le componenti isolate del grafo LASD 2004- 05 2 Breadth-first-search Visita in ampiezza 3 Breadth-first-search (BFS) – 1 G=(V,E) direzionato/non-direzionato s∈V, s = sorgente La BFS esplora gli archi di G alla ricerca dei vertici che sono raggiungibili da s Computa la distanza (= min numero di archi) da s a tutti gli altri vertici raggiunti 1 1 2 23 5 2 3 3 5 4 6 1 1 1 2 s=1 4 1 LASD 2004- 05 4 2 4 Breadth-first-search (BFS) –2 G=(V,E) direzionato/non-direzionato s ∈ V, s=sorgente Produce l’albero breadth-first avente come radice s e come nodi tutti i vertici raggiunti Il cammino da s ad un vertice v in tale albero è il cammino minimo (shortest path) da s a v in G Il nome breadth-first-search è dovuto al fatto che l’algoritmo scopre tutti i vertici a distanza k da s prima di scoprire quelli a distanza k+1 LASD 2004- 05 5 Esempio – 1 2 1 1 1 1 Un esempio di applicazione della BFS su di un grafo non orientato Si parte dal nodo a Tra i nodi adiacenti allo stesso nodo si segue l’ordine alfabetico Tra le parentesi è indicato il tempo di scoperta del nodo Una volta visitati tutti i nodi in una componente si inizia nuovamente partendo dal nodo con etichetta lessicograficamente minore (dalla c) Gli archi pieni rappresentano l’albero breadth-first LASD 2004- 05 6 Esempio – 2 1 1 2 Un esempio di applicazione della BFS su di un grafo non orientato Si parte dal nodo a Tra i nodi adiacenti allo stesso nodo si segue l’ordine alfabetico Tra le parentesi è indicato il tempo di scoperta del nodo Una volta visitati tutti i nodi raggiungibili da a si inizia nuovamente partendo dal nodo con etichetta lessicograficamente minore (dalla b) Gli archi pieni rappresentano l’albero breadth-first LASD 2004- 05 7 Breadth-first-search (bfs): algoritmo Per poter individuare i vertici scoperti o meno la procedura colora i vertici utilizzando 3 colori: bianco( ), grigio (G), nero (B) Tutti i vertici hanno inizialmente colore bianco Quando un vertice è incontrato per la prima volta diventa grigio e rimane grigio fino a che tutti i suoi adiacenti sono stati incontrati almeno una volta Quando tutti gli adiacenti di un nodo grigio sono stati visitati allora il nodo diventa nero • Un nodo nero ha solo adiacenti grigi LASD 2004- 05 8 BFS: Notazione per l’algoritmo Input: – BFS(G,s) Grafo G=(V,E) rappresentato con lista di adiacenza; s =sorgente Per ogni u ∈ V color[u] ∈ {B,G,W} π[u] = predecessore di u (o padre di u) • Nota che poiché nella procedura un vertice è scoperto al più una volta esso ha al più 1 padre • π[s] = NIL perché non ha predecessori d[u] = distanza di u da s LASD 2004- 05 9 BFS: Notazione per l’algoritmo Q coda FIFO in cui sono inseriti i nodi grigi restano in Q finché sono grigi La procedura termina quando Q è vuota • tutti gli adiacenti di nodi raggiungibili sono stati esaminati Output π: albero delle precedenze d: distanze da s dei nodi scoperti LASD 2004- 05 10 BFS(G, s) for each u ∈ V – {s} do color[u]ÅW, d[u] Å∞, π[u] ÅNIL endfor color[s]ÅG , d[s] Å0, π[s] ÅNIL, ENQUEUE(Q,s) while Q ≠∅ do Nella coda Q ci saranno u Å head[Q] solo nodi di colore grigio for v ∈ Adj[u] do if color[v]=W then color[v] Å G d[v] Å d[u]+1 π[v] Å u ENQUEUE(Q,v) endif endfor La BFS è alla base di molti DEQUEUE(Q) algoritmi. Le strutture d e π sono utilizzati in tali algoritmi color[u] ÅB endwhile LASD 2004- 05 11 BFS(G,s) : analisi L’inizializzazione costa O(V) Un vertice è bianco solo nella fase di inizializzazione Non gli viene mai ridato quel colore e quindi un nodo viene messo nella coda Q al più 1 sola volta • il while viene iterato O(V) volte Per ogni nodo u estratto dalla coda si esamina, con il for, la sua lista di adiacenza alla ricerca di nodi adiacenti bianchi La lista di adiacenza di un nodo è esaminata al più 1 volta • il nodo infatti una volta uscito da Q non vi rientra La somma delle lunghezze delle liste delle adiacenze è O(E) Quindi il tempo per scandire le liste è O(E) Complessità O(V+E) Se il grafo è denso O(E) Costo del while ∑v Adj(v) = |E| LASD 2004- 05 12 BFS(G,s) : correttezza s ∈ V s = sorgente G=(V,E) δ(s,v) = min numero di archi in un cammino da s a v, se c’è ∞ Lemma1 Lemma2 se non ci sono cammini Per ogni (u ,v)∈ E δ(s,v) ≤ δ(s,u) +1 Dopo che BFS è terminata, per ogni v∈V d[v] ≥ δ(s,v) Teorema • durante BFS ogni vertice v raggiungibile da s è scoperto • alla fine di BFS, per ogni vertice scoperto, d[v]= δ(s,v) • un percorso minimo da s a v è dato dal percorso minimo da s a π[v] più (π[v],v) LASD 2004- 05 13 Dimostrazione Lemma1 Per ogni (u ,v)∈ E δ(s,v) ≤ δ(s,u) +1 Se u è raggiungibile da s allora anche il vertice v è raggiungibile Il percorso minimo da s a v non può essere più lungo dal percorso da s ad u seguito dall’arco (u,v) Se u non è raggiungibile da s allora δ(s,u)= ∞ e la disuguaglianza è soddisfatta LASD 2004- 05 14 Dimostrazione Lemma2 – 1 Al termine di BFS, d[v] ≥ δ(s,v) ∀ v∈V Ipotesi induttiva • d[v] ≥ δ(s,v) ∀ v∈V Base (appena inseriamo s nella coda) • d[s]=0= δ(s,s) • d[v]= ∞ ≥ δ(s,v) ∀ v∈V\{s} • Quindi l’ipotesi induttiva è soddisfatta Per il passo induttivo sfruttiamo il Lemma1 e l’assegnamento d[v]=d[u]+1 LASD 2004- 05 15 Dimostrazione Lemma2 – 2 Passo induttivo • Consideriamo il vertice v scoperto durante l’analisi dei vertici adiacenti al vertice u abbiamo che d[v] = d[u]+1 per il passo dell’algoritmo ≥ δ(s,u) + 1 per l’ipotesi induttiva ≥ δ(s,v) per il Lemma1 • Il vertice v è inserito in Q e non verrà mai più inserito in Q (diventa grigio), quindi il valore di d[v] non cambia più • L’ipotesi induttiva è conservata LASD 2004- 05 16 Breadth-first tree Sia G=(V,E) ed s ∈ V, dopo l’esecuzione di BFS(G,s) definiamo Gπ =(Vπ,Eπ) il sottografo predecessore di G con Vπ={v ∈ V: π[v] ≠ NIL} ∪ {s} Eπ ={(π[v],v) ∈ E : v ∈ Vπ-{s}} Un sottografo predecessore è un breadth-first tree se Vπ è costituito da tutti i vertici raggiungibili da s Se c’è un cammino semplice da s a v in Gπ esso coincide con lo shortest path da s a v in G |Eπ|=|Vπ|-1 LASD 2004- 05 17 Breadth-first tree Sia G=(V,E) ed s ∈ V, dopo l’esecuzione di BFS(G,s) Lemma Gπ è un breadth-first tree Stampa il percorso minimo da s a v Print-Path (G,s,v) if v=s then print s else if π[v] =NIL then “Non ci sono percorsi tra s e v” else Print-Path(G,s, π[v]) print v LASD 2004- 05 18 Depth-first-search Visita in profondità 19 Depth-first-search (DFS) G=(V,E) direzionato/non direzionato La DFS esplora in profondità in grafo G fino a quando è possibile Ad ogni passo l’arco esplorato è quello che esce dal vertice v che è il vertice scoperto più di recente e che ha inesplorati tutti i suoi archi uscenti v v LASD 2004- 05 20 Depth-first-search (DFS) G=(V,E) direzionato/non direzionato (non orientato) Quando tutti gli archi di v sono stati esplorati la ricerca torna indietro (backtrack) per esplorare gli altri archi che escono dal vertice u che ha scoperto v predecessore di v u v Questo processo continua fino a quando sono stati raggiunti tutti i vertici da una sorgente iniziale. Se però rimangono dei vertici inesplorati, allora uno di essi viene scelto come nuova sorgente e la ricerca riparte da essa. LASD 2004- 05 21 Depth-first-search (DFS) π[v]=u v Definiamo Gπ =(V,Eπ) il sottografo predecessore di G con Eπ ={(π[v],v) ∈ E : v ∈ V e π[v]≠NIL} LASD 2004- 05 22 Esempio – grafo non orientato Un esempio di applicazione della DFS su di un grafo non orientato Si parte dal nodo a Tra i nodi adiacenti allo stesso nodo si segue l’ordine alfabetico Tra le parentesi è indicato il tempo di scoperta del nodo Una volta visitati tutti i nodi adiacenti ad un nodo (i) si torna al nodo predecessore (f) si inizia nuovamente la visita scegliendo nodi non visitati [dopo i si visiterà il nodo g] Gli archi pieni rappresentano il sottografo predecessore LASD 2004- 05 23 Esempio – grafo orientato Un esempio di applicazione della DFS su di un grafo orientato Si parte dal nodo a Tra i nodi adiacenti allo stesso nodo si segue l’ordine alfabetico Tra le parentesi è indicato il tempo di scoperta del nodo Una volta visitati tutti i nodi adiacenti ad un nodo (i) si torna al nodo predecessore (e) si inizia nuovamente la visita scegliendo nodi non visitati [dopo i si visiterà il nodo f] Gli archi pieni rappresentano il sottografo predecessore LASD 2004- 05 24 DFS versus BFS Come la BFS, ogni qual volta un vertice v è scoperto scandendo la lista di adiacenza di un vertice u allora viene identificato in u il predecessore di v, cioè π[v]=u Al contrario della BFS, il cui grafo dei predecessori è un albero, il grafo dei predecessori della DFS è una foresta Come accadeva nella BFS i vertici sono colorati durante la ricerca con un colore corrispondente al proprio stato Tutti i vertici sono inizialmente Non appena un vertice è scoperto diventa grigio G Quando tutti i suoi adiacenti sono stati esaminati diventa nero B LASD 2004- 05 25 DFS versus BFS Una particolarità della DFS è l’assegnazione di due timestamp (marche temporali) Rappresentano il tempo in cui un vertice è scoperto ed il tempo in cui è terminata la scansione di tutti i suoi archi uscenti time è una variabile che si incrementa ogni volta viene incontrato un nuovo vertice o finisce la scansione dei suoi adiacenti; inizialmente time=0 d[v] = tempo nel quale v è scoperto la prima volta, cioè quando diventa G f[v] = tempo nel quale finisce la scansione degli adiacenti di v, cioè quando v diventa B • 1 ≤ d[v] < f[v] ≤2|V| LASD 2004- 05 26 DFS(G) for each u ∈ V do color[u]ÅW, π[u] ÅNIL endfor time=0 for each u ∈ V do if color[u]=W then DFS_visit(u) endif endfor DFS_visit(u) color[u] Å G, d(u) Å time, time Å time +1 for each v ∈ Adj[u] do if color[v]=W then π[v] Å u DFS_visit(v) endif endfor color[u] Å B f[u] Å time, time Å time +1 LASD 2004- 05 27 DFS Ogni qual volta la DFS_visit è chiamata dalla DFS il vertice u diventa la radice di un nuovo albero nella depth-first forest Quando la DFS finisce, ogni vertice u in V ha avuto assegnati i valori d[u] e f[u] LASD 2004- 05 28 DFS : analisi L’inizializzazione richiede tempo O(V) DFS_visit è chiamata esattamente 1 volta per ogni vertice v in V Durante la sua esecuzione viene esaminata la lista di adiacenza di v • quindi ogni chiamata alla DFS_visit richiede tempo |Adj[v]| ÎIl tempo totale del for in DFS_visit è ∑v∈ V |Adj[v]| = O(E) ÎIl running time di DFS è O(V+E) LASD 2004- 05 29 DFS : proprietà 1. Il grafo dei predecessori forma una foresta di alberi Questo perché gli alberi depth first rispecchiamo la struttura delle chiamate ricorsive della DFS_visit 2. È possibile caratterizzare un vertice v discendente di un altro vertice u nell’albero Teorema v è discendente di u ⇔ al tempo d[u], v può essere raggiunto da u con un cammino di tutti nodi bianchi LASD 2004- 05 30 DFS : proprietà 3. I tempi di scoperta e finali assegnati ai vertici hanno una struttura a parentesi Se si assegna (u quando si scopre u e si assegna u) quando si è finito di scandire i suoi adiacenti, l’intera sequenza di “scoperte” e “fine scansione” fornisce una sequenza di parentesi innestate ed a 2 a 2 accoppiate Possiamo avere (u … (v …. v) … u) ma non (u … (v …. u) … v) LASD 2004- 05 31 DFS : proprietà Teorema delle parentesi Dato G=(V,E) e u,v ∈V solo 1 dei seguenti 3 casi si può verificare: • [d[u],f[u]] e [d[v],f[v]] sono disgiunti • [d[u],f[u]] è contenuto interamente [d[v],f[v]] e u è discendente di v nell’albero • in [d[v],f[v]] è contenuto interamente in [d[u],f[u]] e v è discendente di u nell’albero Corollario v è un discendente di u ⇔ d[u] f[u] d[v] LASD 2004- 05 f[v] 32 Esercizio Scrivere lo pseudocodice di un algoritmo per il calcolo di tutte le componenti connesse di un grafo non orientato Modificare opportunamente una delle analizzate precedentemente (BFS, DFS) visite Discutere della complessità dell’algoritmo proposto e delle strutture dati utilizzate L’algoritmo deve avere una complessità di tempo O(|V| + |E|) LASD 2004- 05 33
Documenti analoghi
versione stampabile - Dipartimento di Ingegneria dell`informazione e
Dato un grafo G = (V, E) ed un nodo s, detto nodo sorgente, la visita
depth first esplora il grafo andando il più possibile in profondità.
Dato un nodo v appena scoperto, la visita prosegue a par...