2. Alter the algorithm in this section so that it efficiently determines the short- est path from the start node to every node in the graph, instead of just to one destination.
3. Do an analysis of the shortest-path algorithm, counting the number of times that an edge is checked for nodes added to the fringe, for updating edges to the fringe nodes, or to pick the node to move from the fringe to the mini- mum spanning tree.
4. Prove that a breadth-first traversal produces a shortest-path tree for a graph without weights.
5. Prove whether it is always, never, or sometimes true that the order in which the nodes are added to the shortest-path tree is the same as the order in which they are encountered in a breadth-first traversal.
6. Prove whether it is always, never, or sometimes true that the order in which the nodes are added to the shortest-path tree is the same as the order in which they are encountered in a depth-first traversal.
Determining the biconnected components of a network indicates how sta- ble the network can be under degraded conditions. So, if all computers on a network are part of the biconnected component of the related graph, we know that the network will continue to function even if one of the computers is down. In airline scheduling, the biconnected component of the graph for the flight schedule indicates if passengers can be rerouted when an airport is closed because of weather problems.
An articulation point in a connected graph is a node that, when it is removed, causes the graph to no longer be connected. Articulation points of a graph are nodes that are shared between two biconnected components. Nodes D and H in Fig. 6.9 are articulation points. The identification of articulation points and the determination of biconnected components are related.
We could identify the articulation points in a brute force manner by remov- ing one node at a time and using one of our traversal methods to see if the remaining nodes are still connected. If they are, the node we removed is not an articulation point, but if they are not, it is an articulation point. This means that we would have to do N traversals of a graph with N nodes. This process would be O(N2). By keeping a little additional information while we are tra- versing, we can identify the articulation points and the biconnected compo- nents on one traversal.
Think about paths in the graph in Fig. 6.9 that begin at node F. You should see that no matter what order the nodes are visited in, the paths from node F to nodes A, B, and C must go through node D. This means that node D is an articulation point and the subgraph containing nodes A, B, C, and D is a biconnected component.
We base our algorithm on depth-first search. You will recall from Section 6.3.1 that we said a depth-first search will follow edges into a graph until a dead end is reached where there are no unvisited nodes adjacent to the cur- rent node. When we reach a dead end, we will back up, but now our algo- rithm will return information about how high up in the depth-first search tree we could have gone at the dead end. These back edges in the search tree indicate a cycle back in the graph. All the nodes in a cycle must be part of the same biconnected component. The back edge location indicates how far we have to back up in our tree before worrying about finding an articulation point.
To accomplish this algorithm, we will keep a count of how many nodes of the graph we have visited. Each node will be assigned an index number indicating when is it visited. In other words, the first node visited will be numbered 1, the second will be numbered 2, and so on. When we reach a dead end, we will look at all of the adjacent nodes (except for the node we just came from) and will use the smallest index number as our back index. If there is just one adjacent node (the one we just came from), we will return the dead end node’s index as our back index. When we return to a node that is not the root of the search tree, we will compare the back index value that was returned. If that value is greater than or equal to the current node’s index value, the subtree just visited (minus any previously found biconnected components) is a biconnected component. Each internal node of the depth-first search tree will return the smallest value from among the indices of adjacent nodes and any back indices returned to it.
How would this process work in our graph of Fig. 6.9? If we begin at node F, it would be assigned an index of 1. We move to node D (index 2), then nodes B (index 3), A (index 4), and C (index 5). Node C is a dead end, and we have back edges to nodes A, B, and D. The index on node D is smallest, so a value of 2 would be returned to node A as the back index. At node A, because the value of 2 is less than node A’s index, it is not an articulation point. The value of 2 is the smallest so far, and it is also returned to node B. This continues until we get back to node D, where we find that the back index returned is the same as node D’s index, and so the nodes A, B, C, and D make up a bicon- nected component. We return to the root of the search tree at node F and then move off to node E (index 6), followed by node G (index 7), and node H (index 8). We next traverse down to node I (index 9), and because it is a dead end with no adjacent nodes other than H, we return its index as the back index. When node H receives a value of 9 from node I, which is greater than the index of node H, we find another biconnected component with nodes H and I. Node H now considers the values of 1 (the back edge to F), 9 (returned from node I), and 8 (node H’s index), returning the smallest of these to node G and then to node E. This value is then returned by node E to the root node, and because all nodes have been visited, those that remain (nodes D, E, F, G, and H) comprise the final biconnected component. In Fig. 6.10 we see the result of this process, and from this we can see that the articulation points in the original graph are nodes D and H, which are the only nodes that appear in two separate components.
6.6.1
1. Determine the biconnected components of the following graphs:
2. Write an algorithm that determines the biconnected components of a graph using an adjacency matrix.
3. Write an algorithm that determines the biconnected components of a graph using an adjacency list.
A C E
F
G
H H I
B D D
■ FIGURE 6.10 The biconnected components of the graph in Fig. 6.9
6.6.1 EXERCISES
■
A
H
E F
F E
G B
I
D
K C
J a.
A
G
B
H
D
J C
I c.
A
I
E F
G F
G B
J
D H C
K b.
A
I
B
J
D
L H C
K d.
E