Algoritmi di Visita di Grafi Moreno Marzolla

Slides:



Advertisements
Presentazioni simili
Algoritmi e Strutture Dati
Advertisements

Algoritmi e Strutture Dati (Mod. B)
Breath-first search Visita in ampiezza di un grafo Algoritmo Esempio
Breath-first search Visita in ampiezza di un grafo Algoritmo Esempio
Algoritmi e Strutture Dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Un albero è un grafo.
Algoritmi e Strutture Dati (Mod. B)
Algoritmi e Strutture Dati (Mod. B)
Algoritmi e Strutture Dati
1 © Alberto Montresor Algoritmi e Strutture Dati Capitolo 7 - Tabelle hash Alberto Montresor Università di Trento This work is licensed under the Creative.
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 K 4 è planare? Sì!
Algoritmi elementari su grafi
Capitolo 11 Visite di grafi Algoritmi e Strutture Dati.
Master Bioinformatica 2002: Visite di Grafi Algoritmi di visita Scopo: visitare tutti i vertici di un grafo per scoprirne proprietà di vario tipo. Alcune.
Capitolo 11 Grafi e visite di grafi Algoritmi e Strutture Dati Camil Demetrescu, Irene Finocchi, Giuseppe F. Italiano.
Tecniche Algoritmiche/1 Divide et Impera Moreno Marzolla
Statistiche d'ordine Moreno Marzolla Dip. di Scienze dell'Informazione Università di Bologna
Alberi Binari di Ricerca Moreno Marzolla Dip. di Scienze dell'Informazione Università di Bologna
Minimum Spanning Tree Moreno Marzolla
Cammini minimi Moreno Marzolla
Code con priorità Moreno Marzolla Dip. di Scienze dell'Informazione Università di Bologna
Prof.ssa Rossella Petreschi Lezione del 3/12/2013 del Corso di Algoritmica GRAFI e PLANARITA’ Lezione n°15.
Union-Find Moreno Marzolla Dip. di Scienze dell'Informazione Università di Bologna
Progettare algoritmi veloci usando strutture dati efficienti
Cammini minimi in grafi:
Branch and Bound Lezione n°19 Prof.ssa Rossella Petreschi
Branch and Bound Lezione n°14 Prof.ssa Rossella Petreschi
Progettare algoritmi veloci usando strutture dati efficienti
Logica binaria Moreno Marzolla
Algoritmi Avanzati a.a.2013/2014 Prof.ssa Rossella Petreschi
Lezione n°15 Prof.ssa Rossella Petreschi
Algoritmi Avanzati a.a.2011/2012 Prof.ssa Rossella Petreschi
Algoritmi Avanzati a.a.2014/2015 Prof.ssa Rossella Petreschi
Cammini minimi tra tutte le coppie
Algoritmi Avanzati a.a.2011/2012 Prof.ssa Rossella Petreschi
Algoritmi Avanzati Prof.ssa Rossella Petreschi
Algoritmi Avanzati a.a.2011/2012 Prof.ssa Rossella Petreschi
Algoritmi Avanzati a.a.2014/2015 Prof.ssa Rossella Petreschi
Usi (meno scontati) della visita DFS
Algoritmi Avanzati a.a.2010/2011 Prof.ssa Rossella Petreschi
K4 è planare? E K3,3 e K5 sono planari? Sì!
Algoritmi e Strutture Dati
per rappresentare grafi
Lezione n°11 Prof.ssa Rossella Petreschi
Lezione n°12 Prof.ssa Rossella Petreschi
Algoritmi e Strutture Dati
ABBINAMENTO Lezione n°13
Algoritmi e Strutture dati a.a.2010/2011 Prof.ssa Rossella Petreschi
Algoritmi e Strutture Dati
Algoritmi per il flusso nelle reti
Algoritmi per il flusso nelle reti
Branch and Bound Lezione n°18 Prof.ssa Rossella Petreschi
Algoritmi e Strutture Dati
Schema generale, visita in ampiezza e profondità.
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati
Usi (meno scontati) della visita DFS
Progettare algoritmi veloci usando strutture dati efficienti
Algoritmi Avanzati Prof.ssa Rossella Petreschi
Algoritmi e Strutture Dati
Cammini minimi in grafi:
Grafi e problem solving
Algoritmi e Strutture dati a.a.2010/2011 Prof.ssa Rossella Petreschi
Insiemi disgiunti.
Algoritmi e Strutture Dati
Algoritmi e Strutture Dati
HeapSort Stesso approccio incrementale del selectionSort Tipo di dato
Transcript della presentazione:

Algoritmi di Visita di Grafi Moreno Marzolla

Algoritmi e Strutture Dati2 Original work Copyright © Alberto Montresor, Università di Trento, Italy ( Modifications Copyright © 2010, Moreno Marzolla, Università di Bologna, Italy ( This work is licensed under the Creative Commons Attribution-NonCommercial- ShareAlike License. To view a copy of this license, visit or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.

Algoritmi e Strutture Dati3 Attraversamento grafi ● Definizione del problema – Dato un grafo G= ed un vertice s di V (detto sorgente), visitare ogni vertice raggiungibile nel grafo dal vertice s – Ogni nodo deve essere visitato una volta sola ● Visita in ampiezza (breadth-first search) – Visita i nodi “espandendo” la frontiera fra nodi scoperti / da scoprire – Es: Cammini più brevi da singola sorgente ● Visita in profondità (depth-first search) – Visita i nodi andando il “più lontano possibile” nel grafo – Es: Componenti fortemente connesse, ordinamento topologico

Algoritmi e Strutture Dati4 Visita: attenzione alle soluzioni “facili” ● Prendere ispirazione dalla visita degli alberi ● Ad esempio: – utilizziamo una visita BFS basata su coda – trattiamo i “vertici adiacenti” come se fossero i “figli” algoritmo non-visita(grafo G, nodo s) coda := {s} while (coda ≠ ∅ ) do u = coda.dequeue() “visita u” for each “nodo v adiacente a u” do coda.enqueue(v) endfor endwhile Sbagliat o

Algoritmi e Strutture Dati5 Perché non funziona? algoritmo non-visita(grafo G, nodo s) coda := {s} while (coda ≠ ∅ ) do u = coda.dequeue() “visita u” for each “nodo v adiacente a u” do coda.enqueue(v) endfor endwhile AB DC coda = { A }

Algoritmi e Strutture Dati6 Perché non funziona? algoritmo non-visita(grafo G, nodo s) coda := {s} while (coda ≠ ∅ ) do u = coda.dequeue() “visita u” for each “nodo v adiacente a u” do coda.enqueue(v) endfor endwhile AB DC coda = { A } coda = { B, D }

Algoritmi e Strutture Dati7 Perché non funziona? algoritmo non-visita(grafo G, nodo s) coda := {s} while (coda ≠ ∅ ) do u = coda.dequeue() “visita u” for each “nodo v adiacente a u” do coda.enqueue(v) endfor endwhile AB DC coda = { A } coda = { B, D } coda = { D, A, C }

Algoritmi e Strutture Dati8 Perché non funziona? algoritmo non-visita(grafo G, nodo s) coda := {s} while (coda ≠ ∅ ) do u = coda.dequeue() “visita u” for each “nodo v adiacente a u” do coda.enqueue(v) endfor endwhile AB DC coda = { A } coda = { B, D } coda = { D, A, C } coda = { A, C, A, C }

Algoritmi e Strutture Dati9 Perché non funziona? algoritmo non-visita(grafo G, nodo s) coda := {s} while (coda ≠ ∅ ) do u = coda.dequeue() “visita u” for each “nodo v adiacente a u” do coda.enqueue(v) endfor endwhile ● Problema: questo algoritmo non termina se applicato a grafi con cicli

Algoritmi e Strutture Dati10 Idea ● L'algoritmo esplora il grafo a partire da un nodo s – Costruisce un albero T radicato in s che contiene tutti i nodi raggiungibili a partire da s ● Ogni vertice del grafo può essere – inesplorato: Il vertice non è ancora stato incontrato – aperto: l'algoritmo ha incontrato il vertice la prima volta – chiuso: il vertice è stato visitato completamente (tutti gli archi incidenti sono stati esplorati) ● L'algoritmo mantiene un sottoinsieme F  T – Se un nodo v sta in T-F, significa che tutti gli archi incidenti sono stati esplorati (v è chiuso) – Se un nodo v sta in F, non tutti gli archi sono stati esplorati (v è aperto) – Se un nodo non sta in T, allora è inesplorato

Algoritmi e Strutture Dati11 Algoritmo generico per la visita algoritmo visitaGenerica(vertice s)→albero marca tutti i vertici come inesplorati marca il vertice s come aperto inizializza la frangia F e l'albero T inserendovi s while ( F ≠  ) do estrai un vertice u da F if (u è chiuso) then continue; marca u come chiuso visita il vertice u for each arco (u,v) in G do if (v è inesplorato) then marca v come aperto inserisci v in F e (u,v) in T elseif (serveAggiornamento per via di (u,v)) then aggiorna F considerando l'arco (u,v) aggiorna l'albero T mettendo u come nuovo padre di v endif endfor endwhile return T

Algoritmi e Strutture Dati12 Algoritmo generico per la visita (semplificato) algoritmo visita(G, s)→albero rendi “non marcati” tutti i vertici T := s F := { s } “marca” il vertice s while (F ≠  ) do u := F.extract() “visita il vertice u” for each v adiacente a u do if (v non è marcato) then marca il vertice v F.insert(v) v.parent := u endif endfor endwhile return T ● F è l'insieme frontiera (o frangia) ● Il funzionamento di extract() e insert() non è specificato ● T è l'albero che viene costruito dalla visita ● v.parent è il padre di v nell'albero T

Algoritmi e Strutture Dati13 Algoritmo generico per la visita ● Alcune cose da notare: – I nodi vengono visitati al più una volta (marcatura) – Tutti i nodi raggiungibili da s vengono visitati ● Ne segue che T è un albero che contiene esattamente tutti i nodi raggiungibili da s – Ciascun arco viene “percorso” al piú due volte nel caso dei grafi non orientati ( {u,v}, {v,u} ). – La visita avviene in base all'ordine di estrazione ● Complessità – O(n+m)liste di adiacenza – O(n 2 )matrice di adiacenza – n è il numero di vertici, m è il numero di archi

Algoritmi e Strutture Dati14 Visita in ampiezza (breadth first search, BFS) ● Cosa vogliamo fare? – Visitare i nodi a distanze crescenti dalla sorgente ● visitare i nodi a distanza k prima di visitare i nodi a distanza k+1 – Generare un albero BF (breadth-first) ● albero contenente tutti i vertici raggiungibili da s e tale che il cammino da s ad un nodo nell'albero corrisponde al cammino più breve nel grafo – Calcolare la distanza minima da s a tutti i vertici raggiungibili ● numero di archi attraversati per andare da s ad un vertice raggiungibile a partire da s

Algoritmi e Strutture Dati15 Visita in ampiezza (breadth first search, BFS)

Algoritmi e Strutture Dati16 Visita in ampiezza (breadth first search, BFS)

Algoritmi e Strutture Dati17 Visita in ampiezza (breadth first search, BFS)

Algoritmi e Strutture Dati18 Visita in ampiezza (breadth first search, BFS)

Algoritmi e Strutture Dati19 Visita in ampiezza (breadth first search, BFS)

Algoritmi e Strutture Dati20 Visita in ampiezza (breadth first search, BFS) algoritmo BFS(Grafo G, vertice s)→albero for each v in V do v.mark := false T := s F := new Queue() F.enqueue(s) s.mark := true s.dist := 0 while (F ≠  ) do u := F.dequeue() “visita il vertice u” for each v adiacente a u do if (not v.mark) then v.mark := true v.dist := u.dist+1 F.enqueue(v) v.parent := u endif endfor endwhile return T ● Insieme F gestito tramite una coda ● v.mark è la marcatura del nodo v ● v.dist è la distanza del nodo v dal vertice s

Algoritmi e Strutture Dati21 Esempio A B C E G F H I L D M Coda:{F} 0

Algoritmi e Strutture Dati22 Esempio A B C E G F H I L D M Coda:{B,D,I}

Algoritmi e Strutture Dati23 Esempio A B C E G F H I L D M Coda:{D,I,C,A}

Algoritmi e Strutture Dati24 Esempio A B C E G F H I L D M Coda:{I,C,A,E}

Algoritmi e Strutture Dati25 Esempio A B C E G F H I L D M Coda:{C,A,E,H}

Algoritmi e Strutture Dati26 Esempio A B C E G F H I L D M Coda:{A,E,H}

Algoritmi e Strutture Dati27 Esempio A B C E G F H I L D M Coda:{E,H}

Algoritmi e Strutture Dati28 Esempio A B C E G F H I L D M Coda:{H,G}

Algoritmi e Strutture Dati29 Esempio A B C E G F H I L D M Coda:{G}

Algoritmi e Strutture Dati30 Esempio A B C E G F H I L D M Coda:{}

Algoritmi e Strutture Dati31 Esempio A B C E G F H I L D M Coda:{}

Algoritmi e Strutture Dati32 Esempio A B C E G F H I D F BDI ACE G H Albero prodotto dalla visita BFS

Algoritmi e Strutture Dati33 Applicazioni algoritmo print-path(G, s, v) if (v = s) then print s else if (v.parent = nil) then print “no path from s to v” else print-path(G, s, v.parent) print v endif ● La visita BFS può essere utilizzata per ottenere il percorso più breve (minor numero di archi attraversati) fra due vertici ● Ad esempio, il seguente pseudocodice stampa un cammino piú breve tra due nodi s e v – il grafo G è stato precedentemente visitato con l'algoritmo BFS a partire da s e l'albero della visita T è stato creato

Algoritmi e Strutture Dati34 Esempio cammino piú breve da F a G A B C E G F H I D

Algoritmi e Strutture Dati35 Esempio cammino piú breve da F a G A B C E G F H I D I.parent

Algoritmi e Strutture Dati36 Esempio print-path(G, s, v) A B C E G F H I D algoritmo print-path(G, s, v) if v = s then print s else if v.parent = nil then print “no path from s to v” else print-path(G,s,v.parent) print v endif s v

Algoritmi e Strutture Dati37 Esempio Percorso piú breve per uscire dal labirinto? e u

Algoritmi e Strutture Dati38 Esempio Percorso piú breve per uscire dal labirinto? a b c e d g f h i j a b c e d g fh i j

Algoritmi e Strutture Dati39 Visita in profondità (depth first search, DFS) ● Visita in profondità – Utilizzata per coprire l'intero grafo, non solo i nodi raggiungibili da una singola sorgente (diversamente da BFS) ● Output – Invece di un albero, una foresta DF (depth-first) G π =(V,E π ) ● Contenente un insieme di alberi DF – Informazioni addizionali sul tempo di visita ● Tempo di scoperta di un nodo ● Tempo di “terminazione” di un nodo

Algoritmi e Strutture Dati40 Visita in profondità (depth first search, DFS) ● Nodi bianchi = inesplorati ● Nodi grigi = aperti ● Nodi neri = chiusi algoritmo DFS-visit(vertice u) u.mark := gray; time := time+1; u.dt := time; for each v adiacente a u do if (v.mark = white) then v.parent := u; DFS-visit(v); endif endfor “visita il vertice u” time := time+1; u.ft := time; u.mark := black;

Algoritmi e Strutture Dati41 Visita in profondità (depth first search, DFS) global time := 0; // var.globale algoritmo DFS(Grafo G) for each u in V do u.mark := white; u.parent := nil; endfor for each u in V do if (u.mark == white) then DFS-visit(u); endif endfor ● Versione ricorsiva ● time è una variabile globale che contiene il numero di “passi” dell'algoritmo ● v.dt (discovery time): è il tempo in cui il nodo è stato scoperto ● v.ft (finish time): è il tempo in cui il la visita del nodo termina

Algoritmi e Strutture Dati42 Esempio A B C E G F H I L D [1, ] M

Algoritmi e Strutture Dati43 Esempio A B C E G F H I L D [1, ] [2, ] M

Algoritmi e Strutture Dati44 Esempio A B C E G F H I L D [1, ] [2, ] [3, ] M

Algoritmi e Strutture Dati45 Esempio A B E G F H I L D [4, ] [1, ] [2, ] [3, ] C M

Algoritmi e Strutture Dati46 Esempio A B G F H I L D [4, ] [1, ] [2, ] [3, ] [5, ] C E M

Algoritmi e Strutture Dati47 Esempio A B C E G F H I L D [4, ] [1, ] [2, ] [3, ] [6, ] [5, ] M

Algoritmi e Strutture Dati48 Esempio A B C E G F H I L D [4, ] [1, ] [2, ] [3, ] [6, 7] [5, ] M

Algoritmi e Strutture Dati49 Esempio [1, ] A B C E G F H I L D [4, ] [2, ] [3, ] [6, 7] [5, ] [8, ] M

Algoritmi e Strutture Dati50 Esempio [1, ] A B C E G F H I L D [4, ] [2, ] [3, ] [6, 7] [5, ] [8, ] [9, ] M

Algoritmi e Strutture Dati51 Esempio [1, ] A B C E G F H I L D [4, ] [2, ] [3, ] [6, 7] [5, ] [8, ] [9, ] [10, ] M

Algoritmi e Strutture Dati52 Esempio [1, 18] A B C E G F H I L D M [4,15] [2, 17] [3, 16] [6, 7] [5,14 ] [8, 13] [9, 12] [10, 11]

Algoritmi e Strutture Dati53 Esempio L M [19, ] [1, 18] A B C E G F H I D [4,15] [2, 17] [3, 16] [6, 7] [5,14 ] [8, 13] [9, 12] [10, 11]

Algoritmi e Strutture Dati54 Esempio [1, 18] A B C E G F H I D [4,15] [2, 17] [3, 16] [6, 7] [5,14 ] [8, 13] [9, 12] [10, 11] L M [19, ] [20, ]

Algoritmi e Strutture Dati55 Esempio [1, 18] A B C E G F H I D [4,15] [2, 17] [3, 16] [6, 7] [5,14 ] [8, 13] [9, 12] [10, 11] L M [19, 22] [20, 21]

Algoritmi e Strutture Dati56 Proprietà della visita DFS Teorema delle parentesi ● In una qualsiasi visita di profondità di un grafo G=(V,E), per ogni coppia di vertici u,v, una sola delle seguenti condizioni è vera: – Gli intervalli [u.dt, u.ft] e [v.dt, v.ft] sono disgiunti  u,v non sono discendenti l'uno dell'altro nella foresta DF – L'intervallo [u.dt, u.ft] è interamente contenuto in [v.dt, v.ft]  u è discendente di v in un albero DF – L'intervallo [v.dt, v.ft] è interamente contenuto in [u.dt, u.ft]  v è discendente di u in un albero DF ● Corollario – Il vertice v è un discendente del vertice u nella foresta DF per un grafo G se e soltanto se: u.dt < v.dt < v.ft < u.ft

Algoritmi e Strutture Dati57 Foresta DFS F B A D E CG H I M L – Gli intervalli [u.dt, u.ft] e [v.dt, v.ft] sono disgiunti  u,v non sono discendenti nella foresta DF – [u.dt, u.ft] è interamente contenuto in [v.dt, v.ft]  u è discendente di v in un albero DF – [v.dt, v.ft] è interamente contenuto in [u.dt, u.ft]  v è discendente di u in un albero DF [1,18] [2,17] [3,16] [4,15] [5,14] [6,7][8,13] [9,12] [10,11 ] [19,22 ] [20,21 ]

Algoritmi e Strutture Dati58 Applicazioni DFS ● Individuare – le componenti connesse di un grafo non orientato – le componenti fortemente connesse di un grafo orientato

Algoritmi e Strutture Dati59 Componenti connesse (grafo non orientato) ● Due vertici u e v appartengono alla stessa componente connessa se u è raggiungibile da v ● La relazione “u è raggiungibile da v” è di equivalenza – Riflessiva ● u è raggiungibile da se stesso – Simmetrica ● Se u è raggiungibile da v, allora esiste un cammino che connette u e v. Tale cammino può essere percorso a ritroso per dimostrare che v è raggiungibile da u – Transitiva ● Se u è raggiungibile da v, e v è raggiungibile da w, allora u è raggiungibile da w.

Algoritmi e Strutture Dati60 Componenti connesse (grafo non orientato) ● Poiché la relazione di raggiungibilità è di equivalenza, possiamo concludere che tutti i nodi raggiungibili (mediante visita DFS o BFS) da un nodo sorgente u (incluso u) appartengono alla stessa componente connessa

Algoritmi e Strutture Dati61 Componenti connesse (grafo non orientato) ● Per testare se un grafo non orientato è connesso possiamo: – usare l’algoritmo DFS-visit() o BFS() ● Nel caso dell'algoritmo DFS() è necessario applicare solo l'algoritmo DFS-visit(), in modo da fermarsi dopo l'esplorazione della prima componente connessa – il grafo è connesso se e solo se una chiamata di DFS-visit() raggiungerà tutti i vertici. ● Una chiamata di DFS-visit() raggiungerà tutti i vertici contenuti esattamente in una componente connessa

Algoritmi e Strutture Dati62 Componenti Connesse algoritmo CC(G) for each u in V do u.cc := -1; u.parent := NIL; endfor k := 0; for each u in V do if (u.cc < 0) then CC-visit(u,k); k := k+1; endif endfor algoritmo CC-visit(u, k) u.cc := k; for each v adiacente a u do if (v.cc < 0) then v.parent := u; CC-visit(v, k); endif endfor Etichetta con il valore k tutti i nodi della stessa componente connessa cui appartiene u

Algoritmi e Strutture Dati63 Applicazione: floodfill

Algoritmi e Strutture Dati64 Applicazione: floodfill

Algoritmi e Strutture Dati65 Componenti fortemente connesse (Strongly Connected Components) ● Ricordiamo: un grafo orientato G è fortemente connesso se ogni coppia di vertici è connessa da un cammino A B C E D F A B C E D F Questo grafo orientato è fortemente connesso. Questo grafo orientato non è fortemente connesso; ad es., non esiste cammino da D a A.

Algoritmi e Strutture Dati66 Nel mondo reale

Algoritmi e Strutture Dati67 Nel mondo reale

Algoritmi e Strutture Dati68 Componenti fortemente connesse (grafo orientato) ● u e v appartengono alla stessa componente fortemente connessa se e solo se esiste un cammino (orientato) che connette u con v e viceversa ● La relazione di connettività forte è di equivalenza – Riflessiva ● u è raggiungibile da se stesso per definizione – Simmetrica ● Se u è fortemente connesso a v, allora esiste un cammino (orientato) che connette u e v e viceversa. Quindi anche v è fortemente connesso a u. – Transitiva ● Se u è fortemente connesso a v, e v è fortemente connesso a w, allora u è fortemente connesso a w. uv uv w

Algoritmi e Strutture Dati69 Idea ● Due nodi u e v appartengono alla stessa componente fortemente connessa se e solo se valgono entrambe le seguenti proprietà – Esiste un cammino u →→ v ● cioè v è discendente di u in una visita DF che usa u come sorgente – Esiste un cammino v→→u ● cioè u è discendente di v in una visita DF che usa v come sorgente

Algoritmi e Strutture Dati70 Idea ● A(x) = insieme degli antenati del nodo x – cioè insieme di tutti i nodi da cui si può raggiungere x ● D(x) = insieme dei discendenti del nodo x – cioè insieme di tutti i nodi che si possono raggiungere da x ● Per individuare la componente fortemente connessa cui appartiene x, è sufficiente calcolare l'intersezione A(x)  D(x)

Algoritmi e Strutture Dati71 Idea ● Come calcolare D(x)? – D(x) include i nodi raggiungibili da una visita (DF o BF, poco importa) usando x come sorgente ● Come calcolare A(x)? – È sufficiente invertire la direzione di tutti gli archi, ed effettuare una nuova visita (DF o BF) usando ancora x come sorgente ● Nota: il calcolo di A(x) o D(x) richiede tempo O(n+m) x x

Algoritmi e Strutture Dati72 Algoritmo (schematico) algoritmo SCC(Grafo G, nodo x)→lista di nodi L := lista vuota di nodi (1)Esegui DFS(G, x) marcando i nodi visitati (2)Calcola il grafo trasposto G T (inverti la direzione degli archi di G) (3)Esegui DFS(G T, x), mettendo in L i nodi visitati che sono stati marcati durante (1) return L ● (1) costa O(n+m) ● (2) costa O(n+m) ● (3) costa O(n+m)

Algoritmi e Strutture Dati73 Calcolo di tutte le componenti fortemente connesse ● Per calcolare tutte le SCC di un grafo G è necessario eseguire l'algoritmo SCC(G,x) per ogni nodo x  V – Ogni esecuzione di SCC(G,x) costa O(n+m) ● Costo complessivo: O(nm+n 2 ) – Esiste un algoritmo più sofisticato che elenca tutte le SCC di un grafo G in tempo complessivo O(n+m)