CS302 Final Exam: December 4, 2008 - Answers and Grading.


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.

Grading

Scores


Question 2 (Nine Points)

Grading was 1.5 points per question.

Scores


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/EdgeSets
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}

So, the answer is o.

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:

EdgeThe 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-

Thus, the answer is e.

Grading

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.

Scores


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: 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.

Grading

Scores


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.
Here's a good answer:

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);
}

Grading

All good answers had the same general form: 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.

Scores


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 <Edge *> Graph::Min_Hop_Path()
{
  list <Node *> bfsq;
  list <Node *>::iterator bit;
  list <Edge *>::iterator ait;
  list <Edge *> 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;
    }
  }
}

Grading

Again, all answers should have roughly the same form. I broke up points into the following functionalities. However, if your answer didn't have the right form, I assigned points on how well I thought your answer communicated your understanding of the problem.

Scores