Nattee Niparnan
Graph A pair G = (V,E) V = set of vertices (node) E = set of edges (pairs of vertices) V = (1,2,3,4,5,6,7) E = ((1,2),(2,3),(3,5),(1,4),(4, 5),(6,7))
Term you should already know directed, undirected graph Weighted graph Bipartite graph Tree Spanning tree Path, simple path Circuit, simple circuit Degree
Representing a Graph Adjacency Matrix A = |V|x|V| matrix a xy = 1when there is an edge connecting node x and node y a xy = 0otherwise
Representing a Graph Adjacency List Use a list instead of a matrix For each vertex, we have a linked list of their neighbor
Representing a Graph Incidences Matrix Row represent edge Column represent node
Depth First Search
Exploring a Maze
Exploring Problem
Depth-First-Search void explore(G, v) // Input: G = (V,E) is a graph; v V // Output: visited[u] is set to true for all nodes u reachable from v { visited[v] = true previsit(v) for each edge (v,u) E if not visited[u] explore(u) postvisit(v) }
Example Explore(A)
Extend to Graph Traversal Traversal is walking in the graph We might need to visit each component in the graph Can be done using explore Do “explore” on all non-visited node The result is that we will visit every node What is the difference between just looking into V (the set of vertices?)
Graph Traversal using DFS void dfs(G) { for all v V visited[v] = false for all v V if not visited[v] explore(v) }
Complexity Analysis Each node is visited once Each edge is visited twice Why? O( |V| + |E|)
Another Example
Connected Component
Connectivity in Undirected Graph
Connected Component Problem Input: A graph Output: Marking in every vertices identify the connected component Let it be an array ccnum, indexed by vertices
Solution Define global variable cc In previsit(v) ccnum[v] = cc Before calling each explore cc++
DFS visiting time
Ordering in Visit void previsit(v) pre[v] = clock++ void postvisit(v) post[v] = clock++
Ordering in Visit The interval for node u is [pre(u),post(u)] The inverval for u,v is either Contained disjointed Never intersect
DFS in Directed Graph
Type of Edge in Directed Graph
Directed Acyclic Graph (DAG) A directed Graph without a cycle Has “source” A node having only “out” edge Has “sink” A node having only “in” edge How can we detect that a graph is a DAG What should be the property of “source” and “sink” ?
Solution A directed graph is acyclic if and only if it has no back edge Sink Having lowest post number Source Having highest post number
Topological Sorting
Linearization of Graph
Linearization One possible linearization B,A,D,C,E,F Order of work that can be done w/o violating the causality constraints
Topological Sorting Problem
Topological Sorting Do DFS List node by post number (descending) 1,12 2,9 3,84,5 6,7 10,11
Breadth First Search
Distance of nodes The distance between two nodes is the length of the shortest path between them S A 1 S C 1 S B 2
DFS and Length DFS finds all nodes reachable from the starting node But it might not be “visited” according to the distance
Ball and Strings We can compute distance by proceeding from “layer” to “layer”
Shortest Path Problem (Undi, Unit) Input: A graph, undirected A starting node S Output: A label on every node, giving the distance from S to that node
Breadth-First-Search Visit node according to its layer procedure bfs(G, s) //Input: Graph G = (V,E), directed or undirected; vertex s V //Output: visit[u] is set to true for all nodes u reachable from v for each v V visited[v] = false visited[s] = true Queue Q = [s] //queue containing just s while Q is not empty v = Q.dequeue() previsit(v) visited[v] = true for each edge (v,u) E if not visited[u] visited[u] = true Q.enqueue(u) postvisit(v)
Distance using BFS procedure shortest_bfs(G, s) //Input: Graph G = (V,E), directed or undirected; vertex s V //Output: For all vertices u reachable from s, dist(u) is set to the distance from s to u. for all v V dist[v] = -1 dist[s] = 0 Queue Q = [s] //queue containing just s while Q is not empty v = Q.dequeue() for all edges (v,u) E if dist[u] = -1 dist[u] = dist[v] + 1 Q.enqueue(u) Use dist as visited
DFS by Stack procedure dfs(G, s) //Input: Graph G = (V,E), directed or undirected; vertex s V //Output: visited[u] is true for any node u reachable from v for each v V visited[v] = false visited[s] = true Stack S = [s] //queue containing just s while S is not empty v = S.pop() previsit(v) visited[v] = true for each edge (v,u) E if not visited[u] visited[u] = true S.push(u) postvisit(v)
DFS vs BFS DFS goes depth first Trying to go further if possible Backtrack only when no other possible way to go Using Stack BFS goes breadth first Trying to visit node by the distance from the starting node Using Queue