Assistant Professor CSE, BUET GRAPHS A graph G = (V, E) V = set of vertices E = set of edges = subset of V V Thus |E| = O(|V| 2 ) GRAPH VARIATIONS Variations: A connected graph has a path from every vertex to every other In an undirected graph: Edge (u,v) = edge (v,u) No self-loops In a directed graph: Edge (u,v) goes from vertex u to vertex v, notated uv Self loops are allowed. GRAPH VARIATIONS More variations: A weighted graph associates weights with either the edges or the vertices E.g., a road map: edges might be weighted w/ distance A multigraph allows multiple edges between the same vertices E.g., the call graph in a program (a function can get called from multiple points in another function) GRAPHS We will typically express running times in terms of |E| and |V| (often dropping the |s) If |E| ~ |V| 2 the graph is dense If |E| ~ |V| the graph is sparse If you know you are dealing with dense or sparse graphs, different data structures may make sense
REPRESENTING GRAPHS Assume V = {1, 2, , n} An adjacency matrix represents the graph as a n x n matrix A: A[i, j] = 1 if edge (i, j) e E (or weight of edge) = 0 if edge (i, j) e E
GRAPHS: ADJACENCY MATRIX Example: 1 2 4 3 a d b c A 1 2 3 4 1 2 3 ?? 4 GRAPHS: ADJACENCY MATRIX Example: 1 2 4 3 a d b c A 1 2 3 4 1 0 1 1 0 2 0 0 1 0 3 0 0 0 0 4 0 0 1 0 GRAPHS: ADJACENCY MATRIX Space: O(V 2 ). Not memory efficient for large graphs. Time: to list all vertices adjacent to u: O(V). Time: to determine if (u, v) e E: O(1). GRAPHS: ADJACENCY MATRIX The adjacency matrix is a dense representation Usually too much storage for large graphs But can be very efficient for small graphs Most large interesting graphs are sparse E.g., planar graphs, in which no edges cross, have |E| = O(|V|) by Eulers formula For this reason the adjacency list is often a more appropriate respresentation
GRAPHS: ADJACENCY LIST Adjacency list: for each vertex v e V, store a list of vertices adjacent to v Example: Adj[1] = {2,3} Adj[2] = {3} Adj[3] = {} Adj[4] = {3} Variation: can also keep a list of edges coming into vertex
1 2 4 3 GRAPHS: ADJACENCY LIST For directed graphs: Sum of lengths of all adj. lists is out-degree(v) = |E|
veV Total storage: O(V+E) For undirected graphs: Sum of lengths of all adj. lists is degree(v) = 2|E|
veV Total storage: O(V+E)
No. of edges leaving v No. of edges incident on v. Edge (u,v) is incident on vertices u and v. GRAPH DEFINITIONS Path Sequence of nodes n 1 , n 2 , n k Edge exists between each pair of nodes n i ,
n i+1 Example A, B, C is a path GRAPH DEFINITIONS Path Sequence of nodes n 1 , n 2 , n k Edge exists between each pair of nodes n i ,
n i+1 Example A, B, C is a path A, E, D is not a path GRAPH DEFINITIONS Cycle Path that ends back at starting node Example A, E, A
GRAPH DEFINITIONS Cycle Path that ends back at starting node Example A, E, A A, B, C, D, E, A Simple path No cycles in path Acyclic graph No cycles in graph GRAPH SEARCHING Given: a graph G = (V, E), directed or undirected Goal: methodically explore every vertex and every edge Ultimately: build a tree on the graph Pick a vertex as the root Choose certain edges to produce a tree Note: might also build a forest if graph is not connected BREADTH-FIRST SEARCH Explore a graph, turning it into a tree One vertex at a time Expand frontier of explored vertices across the breadth of the frontier Builds a tree over the graph Pick a source vertex to be the root Find (discover) its children, then their children, etc. BREADTH-FIRST SEARCH Input: Graph G = (V, E), either directed or undirected, and source vertex s e V. Output: d[v] = distance (smallest # of edges, or shortest path) from s to v, for all v e V. d[v] = if v is not reachable from s. t[v] = u such that (u, v) is last edge on shortest path s v. u is vs predecessor. Builds breadth-first tree with root s that contains all reachable vertices.
BREADTH-FIRST SEARCH Associate vertex colors to guide the algorithm White vertices have not been discovered All vertices start out white Grey vertices are discovered but not fully explored They may be adjacent to white vertices Black vertices are discovered and fully explored They are adjacent only to black and gray vertices Explore vertices by scanning adjacency list of grey vertices BFS(G,s) 1. for each vertex u in V[G] {s} 2 color[u] white 3 d[u] 4 t[u] nil 5 color[s] gray 6 d[s] 0 7 t[s] nil 8 Q u 9 enqueue(Q,s) 10 while Q = u 11 u dequeue(Q) 12 for each v in Adj[u] 13 if color[v] = white 14 color[v] gray 15 d[v] d[u] + 1 16 t[v] u 17 enqueue(Q,v) 18 color[u] black
white: undiscovered gray: discovered black: finished Q: a queue of discovered vertices color[v]: color of v d[v]: distance from s to v t[u]: predecessor of v initialization access source s BREADTH-FIRST SEARCH: EXAMPLE
r s t u v w x y BREADTH-FIRST SEARCH: EXAMPLE
0
r s t u v w x y s Q: BREADTH-FIRST SEARCH: EXAMPLE 1
0 1
r s t u v w x y w Q: r BREADTH-FIRST SEARCH: EXAMPLE 1
0 1 2 2
r s t u v w x y r Q: t x BREADTH-FIRST SEARCH: EXAMPLE 1 2 0 1 2 2
r s t u v w x y Q: t x v BREADTH-FIRST SEARCH: EXAMPLE 1 2 0 1 2 2 3
r s t u v w x y Q: x v u BREADTH-FIRST SEARCH: EXAMPLE 1 2 0 1 2 2 3 3 r s t u v w x y Q: v u y BREADTH-FIRST SEARCH: EXAMPLE 1 2 0 1 2 2 3 3 r s t u v w x y Q: u y BREADTH-FIRST SEARCH: EXAMPLE 1 2 0 1 2 2 3 3 r s t u v w x y Q: y BREADTH-FIRST SEARCH: EXAMPLE 1 2 0 1 2 2 3 3 r s t u v w x y Q:
ANALYSIS OF BFS Initialization takes O(|V|).
Traversal Loop After initialization, each vertex is enqueued and dequeued at most once, and each operation takes O(1). So, total time for queuing is O(|V|).
The adjacency list of each vertex is scanned at most once. The total time spent in scanning adjacency lists is O(|E|).
Summing up over all vertices => total running time of BFS is O(|V| + |E|) BREADTH-FIRST TREE For a graph G = (V, E) with source s, the predecessor subgraph of G is G t = (V t , E t ) where V t ={veV : t[v] = nil} {s} E t ={(t[v], v) e E : v e V t - {s}} The predecessor subgraph G t is a breadth-first tree if: V t consists of the vertices reachable from s and for all v e V t , there is a unique simple path from s to v in G t that is also a shortest path from s to v in G. The edges in E t are called tree edges. |E t | = |V t | - 1.
DEPTH-FIRST SEARCH (DFS) Explore edges out of the most recently discovered vertex v. When all edges of v have been explored, backtrack to explore other edges leaving the vertex from which v was discovered (its predecessor). Search as deep as possible first. Continue until all vertices reachable from the original source are discovered. If any undiscovered vertices remain, then one of them is chosen as a new source and search is repeated from that source. DEPTH-FIRST SEARCH Input: G = (V, E), directed or undirected. No source vertex given! Output: 2 timestamps on each vertex. d[v] = discovery time (v turns from white to gray) f [v] = finishing time (v turns from gray to black) t[v] : predecessor of v = u, such that v was discovered during the scan of us adjacency list. Depth-first forest
DEPTH-FIRST SEARCH Coloring scheme for vertices as BFS. A vertex is discovered the first time it is encountered during the search. A vertex is finished if it is a leaf node or all vertices adjacent to it have been finished. White before discovery, gray while processing and black when finished processing
GRAY WHITE BLACK 0 2V d[u] f[u] 1 d[u] < f [u] 2 |V| DFS(G) 1. for each vertex u e V[G] 2. do color[u] white 3. t[u] NIL 4. time 0 5. for each vertex u e V[G] 6. do if color[u] = white 7. then DFS-Visit(u) Uses a global timestamp time. DFS-Visit(u) 1. color[u] GRAY // White vertex u has been discovered 2. time time + 1 3. d[u] time 4. for each v e Adj[u] 5. do if color[v] = WHITE 6. then t[v] u 7. DFS-Visit(v) 8. color[u] BLACK // Blacken u; it is finished. 9. f[u] time time + 1 PSEUDOCODE DFS EXAMPLE DFS EXAMPLE 1 | | | | | | | | d f DFS EXAMPLE 1 | | | | | | 2 | | d f DFS EXAMPLE 1 | | | | | 3 | 2 | | d f DFS EXAMPLE 1 | | | | | 3 | 4 2 | | d f DFS EXAMPLE 1 | | | | 5 | 3 | 4 2 | | d f DFS EXAMPLE 1 | | | | 5 | 6 3 | 4 2 | | d f DFS EXAMPLE 1 | 8 | | | 5 | 6 3 | 4 2 | 7 | d f DFS EXAMPLE 1 | 8 | | | 5 | 6 3 | 4 2 | 7 | d f DFS EXAMPLE 1 | 8 | | | 5 | 6 3 | 4 2 | 7 9 | d f DFS EXAMPLE 1 | 8 | | | 5 | 6 3 | 4 2 | 7 9 |10 d f DFS EXAMPLE 1 | 8 |11 | | 5 | 6 3 | 4 2 | 7 9 |10 d f DFS EXAMPLE 1 |12 8 |11 | | 5 | 6 3 | 4 2 | 7 9 |10 d f DFS EXAMPLE 1 |12 8 |11 13| | 5 | 6 3 | 4 2 | 7 9 |10 d f DFS EXAMPLE 1 |12 8 |11 13| 14| 5 | 6 3 | 4 2 | 7 9 |10 d f DFS EXAMPLE 1 |12 8 |11 13| 14|15 5 | 6 3 | 4 2 | 7 9 |10 d f DFS EXAMPLE 1 |12 8 |11 13|16 14|15 5 | 6 3 | 4 2 | 7 9 |10 d f ANALYSIS OF DFS Loops on lines 1-3 & 5-7 take O(V) time, excluding time to execute DFS-Visit.
DFS-Visit is called once for each white vertex veV when its painted gray the first time. Lines 4-7 of DFS-Visit is executed |Adj[v]| times. The total cost of executing DFS-Visit is veV |Adj[v]| = O(E)
Total running time of DFS is O(|V| + |E|). DEPTH-FIRST TREES Predecessor subgraph defined slightly different from that of BFS. The predecessor subgraph of DFS is G t = (V, E t ) where E t ={(t[v], v) : v e V
and t[v] = nil}. How does it differ from that of BFS? The predecessor subgraph G t forms a depth-first forest composed of several depth-first trees. The edges in E t are called tree edges.
TIME-STAMP STRUCTURE IN DFS There is also a nice structure to the time stamps, which is referred to as Parenthesis Structure.
Theorem 22.7 For all u, v, exactly one of the following holds: 1. d[u] < f [u] < d[v] < f [v] or d[v] < f [v] < d[u] < f [u] and neither u nor v is a descendant of the other. 2. d[u] < d[v] < f [v] < f [u] and v is a descendant of u. 3. d[v] < d[u] < f [u] < f [v] and u is a descendant of v.
TIME-STAMP STRUCTURE IN DFS So d[u] < d[v] < f [u] < f [v] cannot happen. Like parentheses: OK: ( ) [ ] ( [ ] ) [ ( ) ] Not OK: ( [ ) ] [ ( ] )
Corollary v is a proper descendant of u if and only if d[u] < d[v]< f [v] < f [u].
DFS: KINDS OF EDGES Consider a directed graph G = (V, E). After a DFS of graph G we can put each edge into one of four classes: A tree edge is an edge in a DFS-tree. A back edge connects a vertex to an ancestor in a DFS-tree. Note that a self-loop is a back edge. A forward edge is a non-tree edge that connects a vertex to a descendent in a DFS-tree. A cross edge is any other edge in graph G. It connects vertices in two different DFS-tree or two vertices in the same DFS-tree neither of which is the ancestor of the other. EXAMPLE OF CLASSIFYING EDGES a d b e f c in DFS forest not in DFS forest tree tree tree tree forward back back cross 61 CLASSIFYING EDGES OF A DIGRAPH (u, v) is: Tree edge if v is white Back edge if v is gray Forward or cross - if v is black (u, v) is: Forward edge if v is black and d[u] < d[v] (v was discovered after u) Cross edge if v is black and d[u] > d[v] (u discovered after v) DFS: KINDS OF EDGES DFS-Visit(u) with edge classification. G must be a directed graph 1. color[u] GRAY 2. time time + 1 3. d[u] time 4. for each vertex v adjacent to u 5. do if color[v] BLACK 6. then if d[u] < d[v] 7. then Classify (u, v) as a forward edge 8. else Classify (u, v) as a cross edge 9. if color[v] GRAY 10. then Classify (u, v) as a back edge 11. if color[v] WHITE 12. then [v] u 13. Classify (u, v) as a tree edge 14. DFS-Visit(v) 15. color[u] BLACK 16. time time + 1 17. f[u] time DFS: KINDS OF EDGES Suppose G be an undirected graph, then we have following edge classification: Tree Edge an edge connects a vertex with its parent. Back Edge a non-tree edge connects a vertex with an ancestor. Forward Edge There is no forward edges because they become back edges when considered in the opposite direction. Cross Edge There cannot be any cross edge because every edge of G must connect an ancestor with a descendant. 64 SOME APPLICATIONS OF BFS AND DFS BFS To find the shortest path from a vertex s to a vertex v in an unweighted graph To find the length of such a path Find the bipartiteness of a graph.
DFS To find a path from a vertex s to a vertex v. To find the length of such a path. To find out if a graph contains cycles APPLICATION OF BFS: BIPARTITE GRAPH Graph G = (V,E) is bipartite iff V can be partitioned into two sets of nodes A and B such that each edge has one end in A and the other end in B
Alternatively: Graph G = (V,E) is bipartite iff all its cycles have even length Graph G = (V,E) is bipartite iff nodes can be coloured using two colours
Note: graphs without cycles (trees) are bipartite APPLICATION OF BFS: BIPARTITE GRAPH non bipartite bipartite:
Question: given a graph G, how to test if the graph is bipartite? APPLICATION OF BFS: BIPARTITE GRAPH For each vertex u in V[G] {s} do color[u] WHITE d[u] partition[u] 0 color[s] GRAY partition[s] 1 d[s] 0 Q [s] while Queue 'Q' is non-empty do u head [Q] for each v in Adj[u] do if partition [u] = partition [v] then return 0 else if color[v] WHITE then color[v] gray d[v] = d[u] + 1 partition[v] 3 partition[u] ENQUEUE (Q, v) DEQUEUE (Q) Color[u] BLACK Return 1 APPLICATION OF DFS: DETECTING CYCLE FOR DIRECTED GRAPH DFS_visit(u) color(u) GRAY d[u] time time + 1 for each v adjacent to u do if color[v] GRAY then return "cycle exists" else if color[v] WHITE then predecessor[v] u DFS_visit(v) color[u] BLACK f[u] time time + 1 APPLICATION OF DFS: DETECTING CYCLE FOR UNDIRECTED GRAPH DFS_visit(u) color(u) GRAY d[u] time time + 1 for each v adjacent to u do if color[v] GRAY and t[u] v then return "cycle exists" else if color[v] WHITE then predecessor[v] u DFS_visit(v) color[u] BLACK f[u] time time + 1 TOPOLOGICAL SORT Want to sort a directed acyclic graph (DAG). B E D C A C E D A B Think of original DAG as a partial order.
Want a total order that extends this partial order. TOPOLOGICAL SORT Performed on a DAG. Linear ordering of the vertices of G such that if (u, v) e E, then u appears somewhere before v.
Topological-Sort (G) 1. call DFS(G) to compute finishing times f [v] for all v e V 2. as each vertex is finished, insert it onto the front of a linked list 3. return the linked list of vertices
Time: O(V + E). EXAMPLE
Linked List: A B D C E 1/ EXAMPLE
Linked List: A B D C E 1/ 2/ EXAMPLE
Linked List: A B D C E 1/ 2/3
E 2/3 EXAMPLE
Linked List: A B D C E 1/4 2/3
E 2/3
1/4 D EXAMPLE
Linked List: A B D C E 1/4 2/3
E 2/3
1/4 D 5/ EXAMPLE
Linked List: A B D C E 1/4 2/3
E 2/3
1/4 D 5/ 6/ EXAMPLE
Linked List: A B D C E 1/4 2/3
E 2/3
1/4 D 5/ 6/7
6/7 C EXAMPLE
Linked List: A B D C E 1/4 2/3
E 2/3
1/4 D 5/8 6/7
6/7 C
5/8 B EXAMPLE
Linked List: A B D C E 1/4 2/3
E 2/3
1/4 D 5/8 6/7
6/7 C
5/8 B 9/ EXAMPLE
Linked List: A B D C E 1/4 2/3
E 2/3
1/4 D 5/8 6/7
6/7 C
5/8 B 9/10
9/10 A PRECEDENCE EXAMPLE Tasks that have to be done to eat breakfast: get glass, pour juice, get bowl, pour cereal, pour milk, get spoon, eat. Certain events must happen in a certain order (ex: get bowl before pouring milk) For other events, it doesn't matter (ex: get bowl and get spoon) PRECEDENCE EXAMPLE get glass pour juice get bowl pour cereal pour milk get spoon eat breakfast Order: glass, juice, bowl, cereal, milk, spoon, eat. PRECEDENCE EXAMPLE Topological Sort
eat juice glass milk cereal bowl spoon consider reverse order of finishing times: spoon, bowl, cereal, milk, glass, juice, eat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 PRECEDENCE EXAMPLE What if we started with juice?
eat juice glass milk cereal bowl spoon consider reverse order of finishing times: spoon, bowl, cereal, milk, glass, juice, eat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 WHY ACYCLIC? Why must directed graph by acyclic for the topological sort problem? Otherwise, no way to order events linearly without violating a precedence constraint. CORRECTNESS PROOF Show if (u, v) e E, then f [v] < f [u].
When we explore (u, v), what are their colors? Note, u is gray we are exploring it Is v gray? No, because then v would be an ancestor of u. (u, v) is a back edge. a cycle (dag has no back edges). Is v white? Then v becomes descendant of u. By parenthesis theorem, d[u] < d[v] < f [v] < f [u]. Is v black? Then v is already finished. Since were exploring (u, v), we have not yet finished u. Therefore, f [v] < f [u].
STRONGLY CONNECTED COMPONENTS G is strongly connected if every pair (u, v) of vertices in G is reachable from one another. A strongly connected component (SCC) of G is a maximal set of vertices C _ V such that for all u, v e C, both u v and v u exist.
COMPONENT GRAPH G SCC = (V SCC , E SCC ). V SCC has one vertex for each SCC in G. E SCC has an edge if theres an edge between the corresponding SCCs in G. G SCC for the example considered:
G SCC IS A DAG
Proof: Suppose there is a path v' v in G. Then there are paths u u' v' and v' v u in G. Therefore, u and v' are reachable from each other, so they are not in separate SCCs.
Lemma 22.13 Let C and C' be distinct SCCs in G, let u, v e C, u', v' e C', and suppose there is a path u u' in G. Then there cannot also be a path v' v in G. TRANSPOSE OF A DIRECTED GRAPH G T = transpose of directed G. G T = (V, E T ), E T = {(u, v) : (v, u) e E}. G T is G with all edges reversed. Can create G T in (V + E) time if using adjacency lists. G and G T have the same SCCs. (u and v are reachable from each other in G if and only if reachable from each other in G T .)
SCC EXAMPLE h f a e g c b d four SCCs HOW CAN DFS HELP? Suppose we run DFS on the directed graph. All vertices in the same SCC are in the same DFS tree. But there might be several different SCCs in the same DFS tree. Example: start DFS from vertex h in previous graph MAIN IDEA OF SCC ALGORITHM DFS tells us which vertices are reachable from the roots of the individual trees Also need information in the "other direction": is the root reachable from its descendants? Run DFS again on the "transpose" graph (reverse the directions of the edges) ALGORITHM TO DETERMINE SCCS SCC(G) 1. call DFS(G) to compute finishing times f [u] for all u 2. compute G T 3. call DFS(G T ), but in the main loop, consider vertices in order of decreasing f [u] (as computed in first DFS) 4. output the vertices in each tree of the depth-first forest formed in second DFS as a separate SCC
Time: O(V + E). EXAMPLE a b c d e f g h 1/ 2/ 3/ 4 6 5/ 7 8/ 11/ 12/ 13/ 9 10 14 15 16 f 4 h 6 g 7 d 9 c 10 a 14 e 15 b 16 DFS on the initial graph G DFS on G T: start at b: visit a, e start at c: visit d start at g: visit f start at h Strongly connected components: C 1 = {a, b, e}, C 2 = {c, d}, C 3 = {f, g}, C 4 = {h} a b c d e f g h COMPONENT GRAPH The component graph G SCC = (V SCC , E SCC ): V SCC = {v 1 , v 2 , , v k }, where v i corresponds to each strongly connected component C i
There is an edge (v i , v j ) e E SCC if G contains a directed edge (x, y) for some x e C i and y e C j The component graph is a DAG a b c d e f g h a b e c d f g h NOTATIONS Extend notation for d (starting time) and f (finishing time) to sets of vertices U _ V: d(U) = min ueU { d[u] } (earliest discovery time) f(U) = max ueU { f[u] } (latest finishing time) a b c d e f g h 1/ 2/ 3/ 4 6 5/ 7 8/ 11/ 12/ 13/ 9 10 14 15 16 C 1 C 2 C 3 C 4 d(C 1 )
f(C 1 )
d(C 2 )
f(C 2 )
d(C 3 )
f(C 3 )
d(C 4 )
f(C 4 )
=11 =16 =1 =10 =2 =7 =5 =6 SCCS AND DFS FINISHING TIMES Proof: Case 1: d(C) < d(C') Let x be the first vertex discovered in C. At time d[x], all vertices in C and C' are white. Thus, there exist paths of white vertices from x to all vertices in C and C'. By the white-path theorem, all vertices in C and C' are descendants of x in depth-first tree. By the parenthesis theorem, f [x] = f (C) > f(C').
Lemma 22.14 Let C and C' be distinct SCCs in G = (V, E). Suppose there is an edge (u, v) e E such that u e C and v eC'. Then f (C) > f (C'). C C' u v x SCCS AND DFS FINISHING TIMES Proof: Case 2: d(C) > d(C') Let y be the first vertex discovered in C'. At time d[y], all vertices in C' are white and there is a white path from y to each vertex in C' all vertices in C' become descendants of y. Again, f [y] = f (C'). At time d[y], all vertices in C are also white. By earlier lemma, since there is an edge (u, v), we cannot have a path from C' to C. So no vertex in C is reachable from y. Therefore, at time f [y], all vertices in C are still white. Therefore, for all w e C, f [w] > f [y], which implies that f (C) > f (C').
Lemma 22.14 Let C and C' be distinct SCCs in G = (V, E). Suppose there is an edge (u, v) e E such that u e C and v eC'. Then f (C) > f (C'). C C' u v y x SCCS AND DFS FINISHING TIMES Proof: (u, v) e E T (v, u) e E. Since SCCs of G and G T are the same, f(C') > f (C), by Lemma 22.14.
Corollary 22.15 Let C and C' be distinct SCCs in G = (V, E). Suppose there is an edge (u, v) e E T , where u e C and v e C'. Then f(C) < f(C'). CORRECTNESS OF SCC When we do the second DFS, on G T , we start with a component C such that f(C) is maximum (b, in our case) We start from b and visit all vertices in C 1
From corollary: f(C) > f(C) in G for all C = C there are no edges from C to any other SCCs in G T DFS will visit only vertices in C 1
The depth-first tree rooted at b contains exactly the vertices of C 1 C 1 C 2 C 3 C 4 a b c d e f g h f 4 h 6 g 7 d 9 c 10 a 14 e 15 b 16 CORRECTNESS OF SCC The next root chosen in the second DFS is in SCC C 2 such that f(C) is maximum over all SCCs other than C 1
DFS visits all vertices in C 2
the only edges out of C 2 go to C 1 , which weve already visited The only tree edges will be to vertices in C 2 Each time we choose a new root it can reach only: vertices in its own component vertices in components already visited C 1 C 2 C 3 C 4 a b c d e f g h f 4 h 6 g 7 d 9 c 10 a 14 e 15 b 16 RUNNING TIME OF SCC ALGORITHM Step 1: O(V+E) to run DFS Step 2: O(V+E) to construct transpose graph, assuming adjacency list rep. Step 3: O(V+E) to run DFS again Step 4: O(V) to output result Total: O(V+E) ACKNOWLEDGEMENTS These slides contain material developed and copyright by: Roger Crawfis(Ohio State university) (Course# CSE680, 2010) David Luebke(Virginia University) (Course# CS332, 2009) Jennifer Welch (Texas A&M University) (Course#CSCE411, 2012) THE END