Graph Searching Algorithms S Tree Breadth-First Search (BFS) Breadth-First Search (BFS) u v w x y z Not discovered Discovered, adjacent white nodes Discovered, no adjacent white nodes Breadth-First Search (BFS) u x v y w z BFS(G, u): 1. Initialize the graph color[u] gray π[u] Nil d[u] 0 for each other vertex color[u] white Breadth-First Search (BFS) x Q v y BFS(G, u): 2. Initialize the queue QØ Enqueue(Q, u) w z u Breadth-First Search (BFS) t=u x Q v y BFS(G, u): 3. While Q ≠ Ø 1) t Dequeue(Q) w z u Breadth-First Search (BFS) u x v y w z Q t=u r = x, v BFS(G, u): 3. While Q ≠ Ø 2) for each r adj to t if color[r] = white color[r] gray π[r] t d[r] d[t] + 1 Enqueue(Q, r) Breadth-First Search (BFS) t=u r = x, v x Q v y BFS(G, u): 3. While Q ≠ Ø 3) color[t] black w z u Breadth-First Search (BFS) t=v u x v y w z Q BFS(G, u): 3. While Q ≠ Ø 1) t Dequeue(Q) 2) for each r adj to t … 3) color[t] black Breadth-First Search (BFS) u x v y w z Q t=v r=y BFS(G, u): 3. While Q ≠ Ø 1) t Dequeue(Q) 2) for each r adj to t … 3) color[t] black Breadth-First Search (BFS) u x v y w z Q t=v r=y BFS(G, u): 3. While Q ≠ Ø 1) t Dequeue(Q) 2) for each r adj to t … 3) color[t] black Breadth-First Search (BFS) u x v y w z Q t=x r= BFS(G, u): 3. While Q ≠ Ø 1) t Dequeue(Q) 2) for each r adj to t … 3) color[t] black Breadth-First Search (BFS) u x v y w z Q t=y r=w BFS(G, u): 3. While Q ≠ Ø 1) t Dequeue(Q) 2) for each r adj to t … 3) color[t] black Breadth-First Search (BFS) u x v y w z Q t=w r=z BFS(G, u): 3. While Q ≠ Ø 1) t Dequeue(Q) 2) for each r adj to t … 3) color[t] black Breadth-First Search (BFS) u x v y w z Q t=z r= BFS(G, u): 3. While Q ≠ Ø 1) t Dequeue(Q) 2) for each r adj to t … 3) color[t] black Breadth-First Search (BFS) u x v y w z BFS(G, u): - the shortest-path distance from u Breadth-First Search (BFS) u x v y w z BFS(G, u): - the shortest-path distance from u - construct a tree Breadth-First Search (BFS) u x v y w z BFS(G, u): - Initialization: |V| - Enqueuing/dequeuing: |V| - Scanning adj vertices: |E| Breadth-First Search (BFS) u x v y w z BFS(G, u): - Initialization: O(|V|) - Enqueuing/dequeuing: O(|V|) - Scanning adjacent vertices: O(|E|) => total running time: O(|V| + |E|) Depth-First Search (DFS) Depth-First Search (DFS) d[u]: when u is discovered f[u]: when searching adj of u is finished u v w Depth-First Search (DFS) timestamp: t d[u] = t d[u]: when u is discovered f[u]: when searching adj of u is finished u v w Depth-First Search (DFS) timestamp: t+1 d[u] = t d[u]: when u is discovered f[u]: when searching adj of u is finished u v d[v] = t+1 w Depth-First Search (DFS) timestamp: t+2 d[u] = t d[u]: when u is discovered f[u]: when searching adj of u is finished u v d[v] = t+1 f[v] = t+2 w Depth-First Search (DFS) timestamp: t+3 d[u] = t d[u]: when u is discovered f[u]: when searching adj of u is finished u v d[v] = t+1 f[v] = t+2 w d[w] = t+3 Depth-First Search (DFS) timestamp: t+4 d[u] = t d[u]: when u is discovered f[u]: when searching adj of u is finished u v d[v] = t+1 f[v] = t+2 w d[w] = t+3 f[v] = t+4 Depth-First Search (DFS) timestamp: t+5 d[u] = t f[u] = t+5 v d[v] = t+1 f[v] = t+2 d[u]: when u is discovered f[u]: when searching adj of u is finished u w d[w] = t+3 f[w] = t+4 Depth-First Search (DFS) d[u] = t f[u] = t+5 v d[v] = t+1 f[v] = t+2 d[u]: when u is discovered f[u]: when searching adj of u is finished u w d[w] = t+3 f[w] = t+4 1. d[u] < f[u] 2. [ d[u], f[u] ] entirely contains [ d[v], f[v] ] 3. [ d[v], f[v] ] and [ d[w], f[w] ] are entirely disjoint Depth-First Search (DFS) u v w x y z Not discovered Discovered, adjacent white nodes Discovered, no adjacent white nodes Depth-First Search (DFS) u v w x y z Not discovered Discovered, adjacent white nodes Discovered, no adjacent white nodes Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization for each u V[G], color[u] white π[u] Nil time 0 Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting color[u] gray d[u] time time + 1 Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. for each adj v of white π[v] u DFS-Visit[v] Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. for each adj v of white π[v] u DFS-Visit[v] Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. for each adj v of white π[v] u DFS-Visit[v] Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. Handling adj vertices 3. color[u] black f[u] time time + 1 Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. Handling adj vertices 3. color[u] black f[u] time time + 1 Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. Handling adj vertices 3. color[u] black f[u] time time + 1 Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. Handling adj vertices 3. color[u] black f[u] time time + 1 Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. Handling adj vertices 3. color[u] black f[u] time time + 1 Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. Handling adj vertices 3. color[u] black f[u] time time + 1 Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. Handling adj vertices 3. color[u] black f[u] time time + 1 Depth-First Search (DFS) u x v y w z DFS(G): 1. Initialization 2. For each u V[G] if color[u] = white DFS-Visit(u) DFS-Visit(u): 1. Initial Setting 2. Handling adj vertices 3. color[u] black f[u] time time + 1 Depth-First Search (DFS) u x v y w z DFS(G): - construct a forest Depth-First Search (DFS) u x v y w z DFS(G): - Initialization: O(|V|) - Traversing vertices: O(|V|) - Scanning adjacent vertices: O(|E|) => total running time: O(|V| + |E|) Topological Sorting Topological Sorting m O(|V|2 + |V||E|) Or O(|V|2) Brute-Force way 1. Find a vertex without edges. 2. Put it onto the front of the list, and remove it from G. 3. Remove all edges to the removed edge. 4. Repeat 1~3. Topological Sorting Using DFS 1. Call DFS(G) 2. When a vertex is finished, put it onto the front of the list. m O(|V| + |E|) Topological Sorting v enters the list before u? At d[u]: Using DFS 1. Call DFS(G) 2. When a vertex is finished, put it onto the front of the list. 1) v is white: d[u] < d[v] < f[u] 2) v is black: f[v] < d[u] 3) v is gray: d[v] < d[u] < f[v] Topological Sorting v enters the list before u? Using DFS 1. Call DFS(G) 2. When a vertex is finished, put it onto the front of the list. 1) v is white: d[u] < d[v] At d[u]: t is gray: d[t] < d[u] < f[t] t is black: f[t] < d[u] Topological Sorting u v w 1. If v is a descendant, d[u] < d[v] < f[v] < f[u] 2. If v is an anscestor, d[v] < d[u] < f[u] < f[v] 3. Otherwise, d[v] < f[v] < d[u] < f[u] or d[u] < f[u] < d[v] < f[v] Depth-First Search (DFS) 1. d[u] < f[u] 2. [ d[u], f[u] ] entirely contains [ d[v], f[v] ] 3. [ d[v], f[v] ] and [ d[w], f[w] ] are entirely disjoint u v w In a depth-first forest, v is a descendant of u if and only if d[u] < d[v] < f[v] < f[u] Topological Sorting 1. If v is a descendant, Contradiction: d[u] < d[v] < f[v] < f[u] G is not acyclic. 2. If v is an anscestor, d[v] < d[u] < f[u] < f[v] 3. Otherwise, d[v] < f[v] < d[u] < f[u] or d[u] < f[u] < d[v] < f[v] At d[u]: 1) v is white: d[u] < d[v] t is gray: d[t] < d[u] < f[t] t is black: f[t] < d[u] Topological Sorting 1. If v is a descendant, Contradiction: d[u] < d[v] < f[v] < f[u] v should be black. 2. If v is an anscestor, d[v] < d[u] < f[u] < f[v] 3. Otherwise, d[v] < f[v] < d[u] < f[u] or d[u] < f[u] < d[v] < f[v] At d[u]: 1) v is white: d[u] < d[v] t is gray: d[t] < d[u] < f[t] t is black: f[t] < d[u] Topological Sorting 1. If v is a descendant, d[u] < d[v] < f[v] < f[u] 2. If v is an anscestor, d[v] < d[u] < f[u] < f[v] 3. Otherwise, d[v] < f[v] < d[u] < f[u] or d[u] < f[u] < d[v] < f[v] At d[u]: 1) v is white: d[u] < d[v] t is white. Topological Sorting 1. If v is a descendant, d[u] < d[v] < f[v] < f[u] 2. If v is an anscestor, d[v] < d[u] < f[u] < f[v] 3. Otherwise, d[v] < f[v] < d[u] < f[u] or d[u] < f[u] < d[v] < f[v] At d[u]: 1) v is white: d[u] < d[v] < f[u] t is white. Topological Sorting 1. If v is a descendant, v will enter the d[u] < d[v] < f[v] < f[u] list before u. 2. If v is an anscestor, d[v] < d[u] < f[u] < f[v] 3. Otherwise, d[v] < f[v] < d[u] < f[u] or d[u] < f[u] < d[v] < f[v] At d[u]: 1) v is white: d[u] < d[v] < f[u] 2) v is black: f[v] < d[u] 3) v is gray: d[v] < d[u] < f[v] Topological Sorting 1. If v is a descendant, v is already in d[u] < d[v] < f[v] < f[u] the list. 2. If v is an anscestor, d[v] < d[u] < f[u] < f[v] 3. Otherwise, d[v] < f[v] < d[u] < f[u] or d[u] < f[u] < d[v] < f[v] At d[u]: 1) v is white: d[u] < d[v] < f[u] 2) v is black: f[v] < d[u] 3) v is gray: d[v] < d[u] < f[v] Topological Sorting 1. If v is a descendant, Contradiction: d[u] < d[v] < f[v] < f[u] G is not acyclic. 2. If v is an anscestor, d[v] < d[u] < f[u] < f[v] 3. Otherwise, d[v] < f[v] < d[u] < f[u] or d[u] < f[u] < d[v] < f[v] At d[u]: 1) v is white: d[u] < d[v] < f[u] 2) v is black: f[v] < d[u] 3) v is gray: d[v] < d[u] < f[v] Strongly Connected Component Strongly Connected Component Strongly Connected Component Strongly Connected Component 3 1. Call DFS(G) 2. Arrange the vertices in order of decreasing f(u) 4 9 5 8 1 2 6 7 Strongly Connected Component 3 1. Call DFS(G) 2. Arrange the vertices in order of decreasing f(u) 3. Compute GT 4 9 5 8 1 2 6 7 Strongly Connected Component 3 1. Call DFS(G) 2. Arrange the vertices in order of decreasing f(u) 3. Compute GT 4. Run DFS(GT) 4 9 5 8 1 2 6 7 Strongly Connected Component 3 1. Call DFS(G) 2. Arrange the vertices in order of decreasing f(u) 3. Compute GT 4. Run DFS(GT) 4 9 5 8 1 2 6 7 Topological Sorting Strongly Connected Component Strongly Connected Component Last f[u] > Last f[u] Strongly Connected Component 3 1. Call DFS(G) 2. Arrange the vertices in order of decreasing f(u) 4 9 5 8 1 2 6 7 Strongly Connected Component 2 1 4 3 Strongly Connected Component 2 1 4 3 Adjacency Matrix of Graphs Directed graph Adjacency-Matrix 1 1 2 3 4 5 2 3 4 5 Adjacency Matrix of Graphs A= AT =