### Question 1 (Six Points)

This graph was easy enough to eyeball and see either three or four augmenting paths. These are shown below -- the left one is made with the paths ABDF, ACDF and ACEF, and the right with the paths ABDF, ACDF, ACEDF and ACEF. Both have a total flow of 229.

It's also clear that the only edges in the flow graph that compose a cut in the original graph are CE, CD and AB.

• Part 1: Three points. If you missed a path, you lost 1.5 points.
• Part 2: Three points. If you included the edge DA (which many of you did by drawing a picture), you lost a point.

### Question 2 (Nine Points)

Grading was 1.5 points per question.
• Problem 1: This is a shortest path problem on a weighted graph: g.
• Problem 2: This is directly from the lecture notes: d.
• Problem 3: While not from the lecture notes, this is the same thing -- if we can characterize the input, we can predict roughly where a number will be, and then clean it up with insertion sort. It will run faster than Quicksort: d.
• Problem 4: When we have no clue, Quicksort will be the fastest: c. I gave 0.5 points for a in case you were thinking of the STL's sort() algorithm, which is different from sets and maps.
• Problem 5: This is depth-first search -- just as in the connected components example from the lecture notes. Breadth-first search would work also. Disjoint Sets do not work here, because you have to add every edge. Think about performance -- if there are only a few nodes connected to the node, depth-first search will finish very quickly. A disjoint-set implementation will have to go through every edge in the graph before it can make that determination, and then you still have to perform find operations to figure out which node is in the same set as the given node: e or f. I gave 0.5 points for j.
• Problem 6: Straight from the lecture notes: j.

### Question 3 (Six Points)

Part 1: With Kruskal's algorithm, you go through the edges in order, and perform unions if the edge connects two nodes in disjoint sets. Below, I'll show the sets that result with each edge addition:

 Node/Edge Sets Start {A},{B},{C},{D},{E},{F},{G},{H},{I},{J},{K},{L} AF {A,F},{B},{C},{D},{E},{G},{H},{I},{J},{K},{L} AE {A,E,F},{B},{C},{D},{G},{H},{I},{J},{K},{L} EF not added {A,E,F},{B},{C},{D},{G},{H},{I},{J},{K},{L} HL {A,E,F},{B},{C},{D},{G},{H,L},{I},{J},{K} JK {A,E,F},{B},{C},{D},{G},{H,L},{I},{J,K} GK {A,E,F},{B},{C},{D},{G,J,K},{H,L},{I} AB {A,B,E,F},{C},{D},{G,J,K},{H,L},{I} BF not added {A,B,E,F},{C},{D},{G,J,K},{H,L},{I} FI {A,B,E,F,I},{C},{D},{G,J,K},{H,L} FJ {A,B,E,F,G,I,J,K},{C},{D},{H,L} DH {A,B,E,F,G,I,J,K},{C},{D,H,L} IJ not added {A,B,E,F,G,I,J,K},{C},{D,H,L} GH {A,B,D,E,F,G,H,I,J,K,L},{C} CG {A,B,C,D,E,F,G,H,I,J,K,L}

Part 2: Prim's algorithm is like Dijkstra's. You maintain a map of nodes not in the tree ordered by their distance from the tree. I'm also keeping the backedges of how the nodes got into the map. Here is each iteration:

 Edge The Map Start (A,0,-) Node A (F,2,AF),(E,5,AE),(B,52,AB) Node F - Edge AF (E,5,AE),(B,52,AB),(I,58,FI),(J,61,FJ),(K,126,FK),(G,176,FG) Node E - Edge AE (B,52,AB),(I,58,FI),(J,61,FJ),(K,126,FK),(G,176,FG) Node B - Edge AB (I,58,FI),(J,61,FJ),(K,126,FK),(G,159,BG),(C,188,BC) Node I - Edge FI (J,61,FJ),(K,126,FK),(G,159,BG),(C,188,BC) Node J - Edge FJ (K,46,JK),(G,159,BG),(C,188,BC) Node K - Edge JK (G,49,GK),(H,157,KH),(L,171,KL),(C,188,BC) Node G - Edge GK (H,103,GH),(C,108,CG),(D,136,DG),(L,171,KL) Node H - Edge GH (L,39,HL),(D,62,HD),(C,108,CG) Node L - Edge HL (D,62,HD),(C,108,CG) Node D - Edge HD (C,108,CG) Node C - Edge CG -

Three points per. 40% off if you switched the two. Answering m or n was worth a point in part 1. Answering d or b was worth a point in part 2. Answering f or c was worth a half a point in part 2.

### Question 4 (Nine Points)

Part 1: Edmonds-Karp: Here you find the augmenting path with the least number of intermediate nodes. Obviously, the first is going to be ADHI as it is the only path with four nodes. That has a flow of 26. Next, you can choose any path with five nodes. There are 4 of these:
• ABCFI
• ABEFI
The only only one that is in the answer list is ABEFI, with a flow of 20. The answer is y.

Part 2: The Max Flow Path: The maximum flow path through the graph is ABCFI with a flow of 82. After that, you have to start with edge AD, and finish with edge HI, because edge FI's remaining capacity is 24. The path ADHI uses both of those edges and has the maximum flow of 26. The answer is g.

Part 3: Greedy DFS: If we do a depth-first search where we always use the maximum capacity edge from a node, the first path will be ADHFI with a flow of 38. The next path will be ABCFI with a flow limited by edge FI, whose capacity is now 68. Thus, the answer is u.

• Part 1: Three for y, 1.5 for z, 1.5 for 1, 1.5 for 2, 1 for 3, 1 for 4.
• Part 2: Three for g, 2 for e, 1.5 for f, 1 for h, 1 for i, 1 for j, 1 for k.
• Part 3: Three for u, 2 for v, 1 for w, 1 for x.

### Question 5 (12 points)

The basic outline of Quicksort is to find a pivot, partition around the pivot, and then call Quicksort recursively on the two partitions. To make it fast, though, we need to do two things:

1. Use insertion sort when the array is sufficiently small. In the lecture notes, that size was 7. If you did any reasonable size, it counted.

2. Choose the pivot to be the median of the first, last and middle elements.

 ```void quick_sort(double *array, int size) { double p[3]; int index; if (size <= 7) { insertion_sort(array, size); return; } p[0] = array[0]; p[1] = array[size-1]; p[2] = array[size/2]; insertion_sort(p, 3); index = partition(array, size, p[1]); quick_sort(array, index); quick_sort(array+index, size-index); } ```

• Using insertion sort lower than a threshold value: 2 points if the threshold value is bigger than three. If it was three, and you were doing it for correctness rather than performance, then you got 1.5 points.
• Finding a pivot that is the middle of the first/last/middle elements: 4 points
• Correct partition call: 2 point
• Correct recursive calls: 4 points
If your answer didn't have the correct form, you lost points. I was also more picky about syntax and types, especially in the partition and recursive calls. If you didn't use types correctly, you also lost points.

### Question 6 (17 points)

This is a standard breadth-first search of an unweighted graph. You maintain a queue of nodes that you have not visited yet.

 ```list Graph::Min_Hop_Path() { list bfsq; list ::iterator bit; list ::iterator ait; list path; Node *n, *n2; Edge *e; source->tmp = 1; bfsq.push_back(source); while (1) { if (bfsq.empty()) return path; bit = bfsq.begin(); n = *bit; bfsq.erase(bit); if (n != sink) { for (ait = n->adj.begin(); ait != n->adj.end(); ait++) { e = *ait; n2 = e->to; if (n2->tmp == 0) { n2->tmp = 1; n2->backedge = e; bfsq.push_back(n2); } } } else { while (n != source) { path.push_front(n->backedge); n = n->backedge->from; } return path; } } } ```