CS302 Final Exam - May 14, 2026 - Answers and Grading

As always, quite a few questions came from banks, so I give detailed answers according to the example exam, and then I give information on answers to other questions from the bank.

Questions 1 and 2 are logistical.


Question 3

Part 1

The cities are nodes and the routes are edges. The cost of each route is the edge. You want to get from A to B with the cheapest total path. This is shortest path on a weighted graph: Dijkstra's algorithm - 3 points. Running time is O(R log C) - 1 point.

Part 2

All of the routes have the same cost, so you want the smallest number of routes to get from A to B. This is shortest path in an unweighted graph: BFS - 3 points. 1 point for Dijkstra. Running time O(R+C) - 1 point.

Part 3

We want to be able to reach all cities with the cheapest cost. This is Minimum Spanning Tree - three points. Running time is O(R log C) - 1 point.

Part 4

This is the minimum cut between Bangor and San Diego. That is solved with Network Flow - 3 points. Running time is X - 1 point.

Part 5

This is a connectivity problem -- DFS - 3 points. Running time is O(R+C) - 1 point.
Your specific problems: The answers to your problems, and their grading, are appended to your exam that I returned to you.


Question 4

Hashes

I use a single hash for all of the parts of question 4. You'll note that each part has its own hash -- here's how the overall hash corresponds to the hashes for each part:
Hash    |  Part-1   Part-2   Part-3   Part-4   Part 5
----    -  ------   ------   ------   ------   ---- -
367a7   |  5b456    369ff    d720f    cad1b    367a7
22c95   |  22c95    40328    2ee12    c0414    7b84a
369ff   |  5b456    369ff    d720f    cad1b    367a7
535d5   |  535d5    31c55    a0f7a    76b08    46afb
5b456   |  5b456    369ff    d720f    cad1b    367a7
a1fbd   |  a1fbd    448eb    7c450    8c9d4    8667e
In your grading file, I graded the questions in the following order: BFS, DFS, Topological, MST, Min-Cut.

BFS

Your breadth-first search will order the nodes by their distance from A: So that answer will be AB, then DGH in any order, then FE, then IC in any order. To show the other answers, I'll separate nodes by commas, and when there are multiple nodes together between commas, those nodes can be in any order. So this example problem will be "A,B,DGH,F,E,IC".

Here are the answers for the banks, keyed by the hash at the bottom of the quetion:

22c95 A,D,BCHE,IF,G
535d5 A,BD,IFG,CEH
5b456 A,B,DGH,F,E,IC
a1fbd A,BG,DE,IF,C,H
Grading: I calculated the longest prefix of your answer that is part of a legal BFS. Then I took that number and multiplied by 4/9 and rounded to the nearest 0.1. So, for example, if your hash was 22c95 and you answered ADBCHIEFG, then your longest legal prefix is ADBCH -- you needed E before I. So your answer is 20/9 = 2.2.

DFS

Let's model this by simulating the recursive calls. I don't call DFS(x) if x is visited.
                                                Visited   
Call                                    Print   ABCDEFGHI
DFS(A)                                    A     X
  DFS(B)                                  B     XX
    DFS(H)                                H     XX     X
      DFS(D)                              D     XX X   X
        DFS(G)                            G     XX X  XX
      DFS(E)                              E     XX XX XX
        DFS(C)                            C     XXXXX XX
        DFS(I)                            I     XXXXX XXX
          DFS(F)                          F     XXXXXXXXX

We can stop here, since all nodes are visited.  ABHDGECIF.
Grading -- Same as BFS -- longest prefix that is part of a legal DFS.

Topological Sort

You can eyeball this and do a pretty good job, but let's run through the algorithm. Let's look at the number of incident edges to each node:
K L M N O P Q R S
1 1 0 0 0 3 3 1 1
So you can start with MNO. When you remove those nodes and their edges, you get:
K L M N O P Q R S
1 1 0 0 0 1 2 0 0
That gives you R and S. When you remove those nodes and their edges, you get:
K L M N O P Q R S
1 1 0 0 0 0 2 0 0
So you add P. Remove that:
K L M N O P Q R S
0 1 0 0 0 0 1 0 0
That gives you K. Remove that:
K L M N O P Q R S
0 0 0 0 0 0 0 0 0
So that gives you Q and L. The final answer: MNORSPKQL. Obviously, there are a lot of legal answers here, so I tested your answer to see if it was legal.

Grading -- Same as BFS -- longest prefix that is part of a legal Topological Sort.

Minimum Spanning Tree

You simply go through Kruskal's algorithm, going through the edges in order, and if they connect nodes in different disjoint sets, you perform and union and add the edge to the MST.

For example:

Edge       Disjoint-Sets       Part of MST
           ABCDEFGHI
IF              1  1               Yes
HE             21 21               Yes
HI             22 22               Yes
EB          2  22 22               Yes
FC          22 22 22               Yes
GD          22222222               Yes
DE          22222222               No
DA         222222222               Yes

Done:  Answer: IF,HE,HI,EB,FC,GD,DE,DA.
Grading: You get the number of edges that are part of the MST. If you gave more, then you lost one "edge" for every extra edge. Then multiply the answer by 1/2.

Minimum Cut

This is an eyeball exercise. There are two distinct subgraphs: SADET and SBCFT. With SBCFT, it should be clear that SB and SC are the edges that belong to the cut. With SADET, it is also clear that DT and ET are the edges that belong to the cut. So the answer is SB,SC,DT,ET.

Grading: The answer was the same for every part. Grading was the same as Topological Sort, with no multiplier.


Question 5

If a problem is in P, then given inputs of size n the running time of P is a polynomial of n, such as n3 + n2 + 1.

When a problem is in NP, then a given input evaluates to either "yes" or "no". To be in NP, you need to be able to verify a "yes" answer in polynomial time.

Grading: 4 points for P, and 4 for NP. You needed to mention the verification to receive full credit.


Question 6

Grading here was three points per question, with some partial credit.

Part 1

Everything inside the for loop is O(1), so the answer is O(n).

Part 2

The outer loop runs in O(2n) iterations, and the inner loop is O(log m). So the answer is O(2n(log m)). You got 1.5 in partial credit for having 2n in your answer, and 1.5 for having (log m).

Part 3

Finding a single augmenting path uses breadth-first search, so the running time is O(V+E). I haven't said whether or not the graph is connected, so O(E) is not correct (it was only a 0.2 point deduction).

Part 4

You want to find the shortest path from S to T, with every edge having a weight of 1 -- it's BFS. Hopefully, you can eyeball this graph and see the if you use FD, then you'll clearly have the shortest hop path. The answer is: SEFDT.


Question 7

We pull 2 off of the queue. It has a distance of 35. We process its edges. The first is [3:43], which sets 3's distance to 35+43 = 78. That sets ninc[3] to 0, so 3 gets added to the queue.

Next, we process [4:1]. That improves 4's distance to 36, so we set 4's distance to 36. ninc[4] is set to 1.

Next, we process [6:45]. That doesn't improve 6's distance; however it does set ninc[6] to 0, so 6 gets added to the queue.

Finally, we process [8:35]. That doesn't improve 8's distance. We set ninc[8] to 3, and we're done.

The answers are:

D:3:78
D:4:36
Q:3
Q:6
Here are the four answers for each of the questions in the bank. The hash is the last line of the question:

hash   |  Event-1 Event-2 Event-3 Event-4
----   -  ------- ------- ------- -------
c3f81  |  D:5:43  D:9:9   Q:3     Q:5
d3f7d  |  D:3:74  D:9:39  Q:3     Q:4
53693  |  D:3:78  D:4:36  Q:3     Q:6
17cc6  |  D:3:31  D:7:45  Q:2     Q:3

Grading: Two points per event. You got 1.5 if you got the right node for "D", but the wrong distance.

Question 8

We have the following edges in the path:
SA with a capacity of 77.
AC with a capacity of 40.
CT with a capacity of 44.
Thus, the flow through the path is 40. We subtract 40 from SA and CT, to leave capacities of 37 and 4 respectively. That deletes the edge AC.

We also add reverse edges with flows of 40, so we add AS and TC with capacities of 40. We add 40 to the capacity of CA, so its capacity is now 62. So the answer is:

SA:37
AC:X
CT:4
AS:40
TC:40
CA:62
Here are the answers for the four questions in the bank, sorted alphabetically. The hash is the last line of the question:

64715 | AC:X AS:39 CA:60 CT:5 SA:39 TC:39
66abe | AC:X AS:40 CA:62 CT:4 SA:37 TC:40
a01ef | AC:X AS:39 CA:57 CT:6 SA:38 TC:39
e9d0e | AC:X AS:36 CA:57 CT:5 SA:38 TC:36

Grading: 1.5 points per modification. If you got the capacity wrong, you only got 0.7 for that modification.


Questions 9-12

Step 1

Simply implement this as a recursive function:

double BIF::bif(int x)
{
  if (x < 0) return -1;
  if (x > 100) return -1;
  if (x == 100 || x == 99) return 1;
  return (x + A) / (x + B) * bif(x+1) * bif(x+2);
}

Step 2

Add a cache. I added the following to the class definition:

  protected:
    vector <double> cache;

Then I access it when it's set, and otherwise set it:

double BIF::bif(int x)
{
  if (x < 0) return -1;
  if (x > 100) return -1;
  if (x == 100 || x == 99) return 1;
  if (cache.size() != 99) cache.resize(99, -1);
  if (cache[x] != -1) return cache[x];
  cache[x] = (x + A) / (x + B) * bif(x+1) * bif(x+2);
  return cache[x];
}

Step 3

Remove the recursion. Now, instead of recursion, you need a for. loop that goes from 100 (or 98) down to x:

double BIF::bif(int x)
{
  int i;

  if (x < 0) return -1;
  if (x > 100) return -1;
  cache.resize(101);
  cache[100] = 1;
  cache[99] = 1;
  for (i = 98; i >= x; i--) cache[i] = (i + A) / (i + B) * cache[i+1] * cache[i+2];
  return cache[x];
}

Step 4

Minimize the cache -- since you only look at elements i+1 and i+2 of the cache, you only need two elements in the cache:

double BIF::bif(int x)
{
  int i;

  if (x < 0) return -1;
  if (x > 100) return -1;
  cache.resize(2);
  cache[0] = 1;
  cache[1] = 1;
  for (i = 98; i >= x; i--) cache[i%2] = (i + A) / (i + B) * cache[0] * cache[1];
  return cache[x%2];
}

Grading

The point values were 6, 8, 6 and 3. Some common deductions: