f02 visite bfs e dfs - caprera.dia.unisa.itcaprera.dia.unisa.it/lasd/slide/f02visite.pdf · albero,...
TRANSCRIPT
Visite in Grafi
BFS e DFS
LASD 2004- 05 2
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
3
Breadth-first-search
Visita in ampiezza
LASD 2004- 05 4
Breadth-first-search (BFS) – 1
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
G=(V,E) direzionato/non-direzionato s∈V, s = sorgente
s=1
45
1 2
3
1
1
2
2
54
1 2 3
6
1
12
3
4
LASD 2004- 05 5
Breadth-first-search (BFS) –2
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 vin 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
G=(V,E) direzionato/non-direzionato s ∈ V, s=sorgente
LASD 2004- 05 6
Esempio – 1
Un esempio di applicazione della BFS su di un grafo non orientatoSi parte dal nodo aTra i nodi adiacenti allo stesso nodo si segue l’ordine alfabeticoTra le parentesi è indicato il tempo di scoperta del nodoUna 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
1
1
1 1
2
LASD 2004- 05 7
Esempio – 2
Un esempio di applicazione della BFS su di un grafo non orientatoSi parte dal nodo aTra i nodi adiacenti allo stesso nodo si segue l’ordine alfabeticoTra le parentesi è indicato il tempo di scoperta del nodoUna 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
1
12
LASD 2004- 05 8
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 9
BFS: Notazione per l’algoritmoInput: – 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 10
BFS: Notazione per l’algoritmo
Q coda FIFO in cui sono inseriti i nodi grigirestano in Q finché sono grigiLa 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 11
La BFS è alla base di molti algoritmi. Le strutture d e πsono utilizzati in tali algoritmi
Nella coda Q ci saranno solo nodi di colore grigio
BFS(G, s)for each u ∈ V – {s} do color[u] W, d[u] ∞, π[u] NIL endforcolor[s] G , d[s] 0, π[s] NIL, ENQUEUE(Q,s) while Q ≠∅ do
u head[Q]for v ∈ Adj[u] do
if color[v]=W then color[v] Gd[v] d[u]+1π[v] uENQUEUE(Q,v)
endifendforDEQUEUE(Q)color[u] B
endwhile
LASD 2004- 05 12
BFS(G,s) : analisiL’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 13
BFS(G,s) : correttezzaG=(V,E) s ∈ V s = sorgente
δ(s,v) = min numero di archi in un cammino da s a v, se c’è
∞ se non ci sono cammini
Lemma1 Per ogni (u ,v)∈ E δ(s,v) ≤ δ(s,u) +1
Lemma2 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 14
Dimostrazione Lemma1
Per ogni (u ,v)∈ E δ(s,v) ≤ δ(s,u) +1Se u è raggiungibile da s allora anche il vertice v è raggiungibileIl 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 15
Dimostrazione Lemma2 – 1
Al termine di BFS, d[v] ≥ δ(s,v) ∀ v∈VIpotesi 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 16
Dimostrazione Lemma2 – 2
Passo induttivo• Consideriamo il vertice v scoperto durante l’analisi
dei vertici adiacenti al vertice u abbiamo ched[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 17
Breadth-first tree
Un sottografo predecessore è un breadth-first tree seVπ è costituito da tutti i vertici raggiungibili da sSe c’è un cammino semplice da s a v in Gπ essocoincide con lo shortest path da s a v in G|Eπ|=|Vπ|-1
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}}
LASD 2004- 05 18
Breadth-first tree
Sia G=(V,E) ed s ∈ V, dopo l’esecuzione di BFS(G,s)
Lemma Gπ è un breadth-first tree
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
Stampa il percorso minimo da s a v
19
Depth-first-search
Visita in profondità
LASD 2004- 05 20
Depth-first-search (DFS)
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
G=(V,E) direzionato/non direzionato
v v
LASD 2004- 05 21
Depth-first-search (DFS)
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 vpredecessore di 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.
G=(V,E) direzionato/non direzionato (non orientato)
u
v
LASD 2004- 05 22
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 23
Esempio – grafo non orientato
Un esempio di applicazione della DFS su di un grafo non orientatoSi parte dal nodo aTra i nodi adiacenti allo stesso nodo si segue l’ordine alfabeticoTra le parentesi è indicato il tempo di scoperta del nodoUna 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 24
Esempio – grafo orientato
Un esempio di applicazione della DFS su di un grafo orientatoSi parte dal nodo aTra i nodi adiacenti allo stesso nodo si segue l’ordine alfabeticoTra le parentesi è indicato il tempo di scoperta del nodoUna 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 25
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 inizialmenteNon appena un vertice è scoperto diventa grigio GQuando tutti i suoi adiacenti sono stati esaminati diventa nero B
LASD 2004- 05 26
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 uscentitime è una variabile che si incrementa ogni volta viene incontrato un nuovo vertice o finisce la scansione dei suoi adiacenti; inizialmente time=0d[v] = tempo nel quale v è scoperto la prima volta, cioè quando diventa Gf[v] = tempo nel quale finisce la scansione degli adiacenti di v, cioè quando v diventa B
• 1 ≤ d[v] < f[v] ≤2|V|
DFS versus BFS
LASD 2004- 05 27
DFS(G)for each u ∈ V do color[u] W, π[u] NIL endfortime=0for each u ∈ V do
if color[u]=W then DFS_visit(u) endifendfor
DFS_visit(u)color[u] G, d(u) time, time time +1for each v ∈ Adj[u] do
if color[v]=W then π[v] uDFS_visit(v)
endifendforcolor[u] Bf[u] time, time time +1
LASD 2004- 05 28
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 29
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 30
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 vdiscendente di un altro vertice u nell’alberoTeorema v è discendente di u ⇔ al tempo d[u], v
può essere raggiunto da u con un cammino di tutti nodi bianchi
LASD 2004- 05 31
DFS : proprietà3. I tempi di scoperta e finali assegnati ai
vertici hanno una struttura a parentesiSe 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 32
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 in [d[v],f[v]] e u è discendente di v nell’albero
• [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]
d[v] f[v]f[u]
LASD 2004- 05 33
Esercizio
Scrivere lo pseudocodice di un algoritmo per il calcolo di tutte le componenti connesse di un grafo non orientato
Modificare opportunamente una delle visite analizzate precedentemente (BFS, DFS)
Discutere della complessità dell’algoritmo proposto e delle strutture dati utilizzate
L’algoritmo deve avere una complessità di tempo O(|V| + |E|)