####.##.## #....#..## #.####.#.# #......#.# #####....# ##########
--- template:dfs What order will the DFS traversal visit the nodes in the graph on the right when we start DFS at A? -- There are more than one possibilities. The exact order is determine by how the graph is stored and how we access the nodes adjacent to a given node. Let's look at some possible traversals --- template:dfs - start with A (visited: A) -- - we have three choices for the next node: B, F, or H; let's pick F (visited: A, F) -- - from F, we can either go to D or H; let's pick H (visited A,F,H) -- - at H, the only choices are A and F and they are both visited, so we go back to F and look for other options; the only option is D (visited: A,F,H,D) -- - from D, we can got to E, G, or C (since F has been visited before); let's pick G (visited: A,F,H,D,G) -- - G has no un-visited neightbors, so we go back to D; let's pick E (visited: A,F,H,D,G,E) -- - E's only un-visited neighbor is B, so we go there; (visited: A,F,H,D,G,E,B) -- - B's unvisited neighbor is C, so we go there; (visited: A,F,H,D,G,E,B,C) -- - C's unvisited neighbor is J, so we go there; (visited: A,F,H,D,G,E,B,C,J) -- At this point we have visited all the nodes and our traversal is: A, F, H, D, G, E, B, C, J But an algorihtm would need to verify that all the nodes have been visited. --- template: dfs Here are two other DFS traversals starting at node A: - A, B, E, D, F, H, G, C, J - A, B, C, J, D, E, F, H, G -- __Task__ List all possible traversals starting at node with label J. --- template:dfs An algorithm using the adjacency list, `adj`, of a graph with `n` nodes and `m` edges, `O(n+m)` .below-column2[ ``` visited[N] - boolean array with all values set initially to false dfs ( start ) if visited[start] return //already processed this node visit/process the node visited[start] = true //mark node as visited for node in adj[start] dfs( node ) ``` ] --- name:bfs ## Breadth First Search Traversal .right-column2[ ] --- template:bfs - visits the nodes in order of their distance from a starting node (distance = path length between nodes) - visit all nodes whose distance from the start node is 1 - visit all nodes whose distance from the start node is 2 - ... -- What order will the BFS traversal visit the nodes in the graph on the right when we start BFS at A? -- Again, the exact ordering will depend on how we store the graph and how we access nodes adjacent to a given node. Here are possible traversals for the graph on the right. - A, B, F, H, C, E, D, G, J -- __Question__ Which of the values in the above traversal could be moved and to where so that it is still a BFS traversal? -- __Task__ Propose a BFS traversal of this graph starting at node J. --- template:bfs An algorithm using the adjacency list `adj` of a graph with `n` nodes and `m` edges, `O(n+m)` ``` visited[N] - boolean array with all values set initially to false queue - to store nodes that we need to go back to bfs ( start ) visited [ start ] = true visit/process the start node queue.push( start ) while queue is not empty node = queue.pop() for n in adj( node ) if ! visited[n] visited [n] = true visit/process n queue.push( n ) ``` --- template:section # Examples and Things to Think About --- ## Graph Implementation Graphs serve many different purposes and their exact implementation needs to suit a specific purpose, so there are generally not among data structures implemented in programming language libraries. Implement a graph. Pick any implementation you want (or try it with all of them). Assume that the graph nodes have integer labels starting with 1 up to N. The graph is undirected and its description is given as a list of edges: `a b` indicates that there is an edge from `a` to `b`. -- How would your implementation be different for a directed graph? -- Modify your code so that it can handle weighted graphs. In this case the graph description would be given as a list of edges: `a b w` indicates that there is an edge from `a` to `b` with weight `w`. --- template: challenge ## Challenge Design algorithms for the following problems. - Given a pair of nodes, find the length of the shortest path from one to the other. Solve this for unweighted and weighted graphs. - Given a node, find the length of the shortest path from that node to all other nodes in the graph. Solve this for unweighted and weighted graphs. - Determine if a graph is connected or disconnected (algorithmically, not visually). If it is disconnected, figure out the number of nodes in each connected component. - Determine if a graph is a tree (algorithmically, not visually). --- ## Solving Problems Try to use your graph implementation to solve the following problems: - [Ab Initio](https://open.kattis.com/problems/abinitio) - the description is long, but it is a fairly easy problem if you have a graph implementation already - [Flying Safely](https://open.kattis.com/problems/flyingsafely) - [Cantina of Babel](https://open.kattis.com/problems/cantinaofbabel) - this is not a difficult problem, but you need to first figure out how to map it to a graph.