You are on page 1of 6

Introduction to Algorithms: 6.

006
Massachusetts Institute of Technology Tuesday, October 17
Instructors: Jason Ku, Muriel Medard, and Silvio Micali Problem Set 5

Problem Set 5
All parts are due Tuesday, October 24 at 11:59PM.

Name: Nanette Wu

Collaborators: Priscilla Wu, Daphne Lin, Jared Schwait

Problem 5-1.

(a)

0 1 1 1 1
1 0 1 1 1

(b) 1. Adjacency Matrix:
1 1 0 1 1
1 1 1 0 1
1 1 1 1 0

Adjacency List:
[ [1,2,3,4],
[0,2,3,4],
[0,1,3,4],
[0,1,2,4],
[0,1,2,3] ]
2 Problem Set 5


0 0 0 0 0 0 0 0 0
0
0 0 0 0 0 0 0 0

0
0 0 0 0 0 0 0 0

0
0 0 0 0 0 0 0 0

2. Adjacency Matrix:
1 1 1 1 0 1 1 1 1

0
0 0 0 0 0 0 0 0

0
0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
Adjacency List:
[[],[],[],[],[0,1,2,3,5,6,7,8],[],[],[],[]]

(c) Given |V | vertices in a graph:


Simple, connected, undirected
Maximum edges: |V |(|V 2
|1)
. Each vertex in V must be connected to every
other vertex, so it will have a degree of |V | 1. To get the total number
of edges, the number of vertices should be multiplied by the degree for each
vertex, or |V | (|V | 1). However, we must also consider that we have
doubly counted an edge between all vertices (u to v and v to u). To maintain
the definition of a simple graph, we divide our product by 2 to achieve the
proper number of edges, which can be justified by the handshaking lemma.
Minimum edges: |V | 1. Using the logic that it takes 1 edge to connect 2
vertices, 2 edges to connect 3 vertices, there must be, at minimum, one fewer
number of edges than vertices in this case. This allows a unique path to exist
from vertex to vertex, and removing any of those edges disconnects the graph.
Simple, unconnected, undirected
Maximum edges: (|V |1)(|V 2
|2)
. Only one node needs to be disconnected
to attain the maximum number of edges. Thus, the remaining nodes can be
thought of as a simple/connected/undirected graph. The maximum number
of edges amongst those |V | 1 nodes is therefore (|V |1)(|V
2
|2)
, for the same
reasoning as in the max edges for the previous graph.
Minimum edges: 0. If a graph is unconnected, then no edges need to exist.
Not simple, connected, undirected
Maximum edges: there can be an infinite number of edges. Because the graph
is not simple, there is no restriction on the number of edges between any two
vertices.
Minimum edges: |V |. Using the reasoning from a simple/connected/undirected
graph, there must be at least |V | 1 edges. However, in order to make the
graph not simple, there must either be a self-loop or a parallel edge, thus
having (|V | 1) + 1 = |V | edges.
Problem Set 5 3

Problem 5-2.

(a) 1. Construct a graph with each vertex representing an airport (total of |a| vertices)
and each edge representing a flight path (total of |r| edges).
2. To find the itinerary with fewest flights, run a BFS on the graph. However, there
should be an additional constraint when running the search; only flights under 1
hour should be added to the frontier when running the search.
3. If a satisfactory itinerary is found, return it. If no such flight exists, the BFS
algorithm should return None.
This algorithm should complete in linear time, O(|a| + |r|). The BFS itself takes
O(|a| + |r|), because it takes O(|a|) to construct the graph and O(|r|) to traverse the
graph, and the comparisons for flight time take constant time.
(b) 1. Construct a graph with each vertex representing an airport (total of |a| vertices)
and each edge representing a flight path (total of |r| edges).
2. To find the itinerary with the fewest flights that do not serve coffee, we will first
use BFS to find all the paths that are viable.
3. Maintain a global variable, bestPath, to store the path with the fewest coffeeless
flights, and maintain another variable, fewestCoffeelessFlights, to store the num-
ber of coffee-less flights in that path.
4. Each time a new path is found with BFS, keep a counter to track the paths num-
ber of coffeeless flight, and compare that value to fewestCoffeelessFlights. If
the counter is smaller, update fewestCoffeelessFlights with the counter value and
update bestPath with the new path. This comparison should take constant time.
5. If a satisfactory itinerary is found, return bestPath. If no such flight exists, the
BFS algorithm should return None.
This algorithm should still complete in linear time, O(|a| + |r|), as described in part
(a). The comparisons take constant time, so the algorithm is still dominated by the
construction and traversal of the graph.
(c) 1. Construct a graph with each vertex representing an airport (total of |a| vertices)
and each edge representing a flight path (total of |r| edges).
2. Now, we utilize graph transformation; construct a new graph such that all viable
paths are lasagna dense, which prunes out the non-lasagna dense possibilities; the
vertices and edges are still defined the same. To create the new graph, use BFS to
traverse through the old graph.
3. For each lasagna containing vertex in the old graph, use BFS to check 3 levels of
d, which checks paths of length 3 rooted in the original lasagna vertex.
4. Now, in the paths of length 3, check for a lasagna containing vertex.
(a) If there is such vertex, recursively check the next 3 levels of d from the new
lasagna vertex and repeat steps 3 and 4.
4 Problem Set 5

(b) If there is no such vertex, remove the edge between the 2nd and 3rd vertex of
the length 3 path. This edge is chosen to be cut because it causes that path to
no longer be lasagna dense.
5. Once there are no more lasagna vertices to check, the new graph is done. Run
a BFS on the new graph to find the shortest lasagna dense flight itinerary. If no
such itinerary exists, the algorithm should return None.
This algorithm takes O(d3 a) because it takes O(d3 ) to use BFS to traverse a lasagna
dense path of depth 3, and the traversal should be made for, worst case, each a lasagna
airport. The lasagna traversal dominates the algorithm (compared to the creation of
the old graph and the final BFS search), so the runtime is O(d3 a).
(d) 1. Construct a graph with each vertex representing an airport (total of |a| vertices)
and each edge representing a flight path (total of |r| edges).
2. Now, we utilize graph transformation; construct a new graph such that each vertex
from the old graph is duplicated c times, given that c is the number of airlines.
Each duplicated node represents an airline that flew into that airport.
3. To create the new graph, we use BFS to traverse the old graph, only looking at
duplicated vertices that have viable flight paths going into them.
4. Then, connect these duplicated vertices to the next airport by having c r flight
paths going out from them. This allows each duplicated vertex to that link to the
next airports c-duplicated nodes.
5. After linking the new vertices, check for any flight paths that link same airlines
to different airports. If a consecutive link is found, remove the path. Otherwise,
continue the traversal until no more vertices can be reached. When this occurs,
the graph creation is done.
6. Now, run a BFS on the new graph to find the shortest flight itinerary with no two
consecutive flights from the same airline. If no such itinerary exists, no viable
path will be found and return None.
Algorithm takes O(c(a + r + 1)) = O((c a) + (c r) + c) because its the sum of:
Duplication of old graph vertices: O(c a); c airlines fly into every airport a,
Connecting each duplicated node to the next airports duplicated nodes: O(c r);
c airlines exist for each possible flight path p, and
Checking for airline consecutive flights: O(c); each check takes constant time,
and there are c duplicated nodes to check.

Problem 5-3.

(a) The upper bound on the number of possible configurations of a Pocket Cube, given
the restrictions, is 7! 37 . Because one corner is fixed, the remaining seven corners
can have 7! permutations. Each corner also has 3 visible faces and orientations, such
that each of those corners can be independent rotated to 37 positions, resulting in a
Problem Set 5 5

total 7! 37 possible configurations. This also stems from the notion of combinatorics
that, given n items with p orientations, the total number of configurations is n! pn .
(b) The maximum and minimum degree of vertices in the Pocket Cube graph is 9. Starting
from a configuration (vertex) in the graph, we know that 3 types of rotations (90, 180,
or 270 degrees) can be done on 3 different faces. This means that each vertex has
3 3 = 9 different paths to walk down, so the maximum and minimum degree of
vertices are the same.
(c) 1. Gills BFS search goes through 3,674,160 configurations. The upper bound from
part (a) is greater than, or specifically three times larger than, the searchs number
of configurations. This is reasonable because the upper bound could have counted
repeats; re-orientations of the cube dont result in different configurations.
2. The diameter of the Pocket Cube graph is 11. This can be determined by counting
the number of frontiers/levels that the BFS search encounters, excluding the initial
frontier of the starting vertex.
3. There are 16,533,720 edges in the Pocket Cube graph. We know that there exist
3,674,160 configurations/vertices in the graph, with 9 possible paths (edges com-
ing out of each vertex) to traverse from each vertex. To get the total number of
edges, we multiple the number of vertices by the possible paths and divide by 2
to remove edges that were doubly counted (i.e. only one of (u,v) and (v,u) need
to be counted for). So, 3, 674, 160 9/2 = 16, 533, 720.
(d) Implement a bidirectional search algorithm.
1. Bidirectionally search from start to goal (forward) and goal to start (backward).
2. Set up the forward search: initialize a parent dictionary, which has one key/value
pair (starting config, None) and a frontier, which has the starting configuration.
3. Set up the backward search: initialize a parent dictionary, which has one key/value
pair (solved config, None) and a frontier, which has the solved configuration.
4. Initialize a counter to ensure that only half of the iterations are run; otherwise, the
algorithm will be slower than Gills original BFS search.
5. While both frontiers arent empty and the counter is less than half of the iterations:
(a) Explore the forward frontier - update the frontier by setting the forward fron-
tier to equal the output of the provided helper function.
(b) Explore the backward frontier - update the frontier by setting the backward
frontier to equal the output of the provided helper function.
(c) For each element in the forward frontier, check if there is a match in the
backward searchs parent dictionary. If a match exists, return the path from
the start to the match using the forward parents dictionary, and return the
path from the match to the goal using the backward parents dictionary.
(d) Increment the counter.
6. If no match was found, return None.
6 Problem Set 5

Given that d, the degree of the graph, is 9 and w, its diameter, is 11, the algorithm
should visit no more than 2(9)d11/2e = 1, 062, 882 configurations because only the
first half of the 12 iterations of frontiers are visited in both directions of the search. In
each iteration of exploring the frontier, the size of the frontier grows much larger, such
that the first 6 frontiers contain a total of 1 + 9 + 54 + 321 + 1847 + 9992 = 12, 224
configurations. When the search is running in both directions (one from the start
config and one from the solved config), 12, 224 2 configurations will be visited,
which is still much less than 2ddw/2e configurations.
(e) Submitted online.

You might also like