Problème 1.

A regional government wants to improve their existing infrastructure between a collection of towns . In specific, the government want to build a minimum number of roads such that there is a route from each town to each other town. The government has been advised by a dubious consultant that in the resulting road network, the number of users of a given road is independent of the presence of alternative routes. The regional government wants to minimise the number of roads it has to built to ensure that one can travel from one town to the other. Furthermore, the government wants to maximize the benefits of the road network by maximizing the number of users of the roads built. Hence, the government wants to only build roads that are expected to be used often. To help the construction plans, the government has asked the dubious consultant to estimate, for each pair of cities, the number of road users that would use the road between these two cities (if that road was built). Now the regional government is looking for a construction plan for a minimum number of roads connecting all towns that see the highest total usage among them.

P1.1

Model the above problem as a graph problem: What are the nodes and edges in your graph, do the edges have weights, and what problems are you trying got answer on your graph?

  • Nodes: Each town in the set of town is represented as a node in the graph. Denote the set of nodes as
  • Edges: Each potential road can be built between two pair of town. Denote it as . Each edge weights represents the estimated number of users who would use the road should it is constructed. Denote the weight of an edge between nodes and as .

The problem can then be modelled as given a weighted undirected graph representing towns and potential roads, find a maximum weight minimum spanning tree of .

Explanation:

  • We need to ensure there is a route from each town to every other town while minimising the number of roads being built, thus the minimum spanning tree of the graph.
  • Among all possible MSTs, we want to find the one with the maximum total edge weight, thus maximum weight MSTs.

P1.2

Provide an algorithm to find the minimum number of roads to build. Explain why your algorithm is correct.

Let be the weight of the edge between nodes and .

Algorithm 35 ConstructionPlan(G,T)\text{ConstructionPlan}(G, T)

Require: Graph G=(T,E)G = (T, E) with nodes TT representing towns and weighted edges EE representing potential roads with weights as estimated road usage

Ensure: Set of edges EE' representing roads to build for maximum weight minimum spanning tree

1:Adjnew list[T]\text{Adj} \gets \text{new list}[|T|]//Adjacency list for graph

2:for (u,v,w)E(u, v, w) \in E do

3:Adj[u].append((v,w))\text{Adj}[u].\text{append}((v, w))

4:Adj[v].append((u,w))\text{Adj}[v].\text{append}((u, w))

5:end for

6:EE' \gets \emptyset

7:Pick an arbitrary node sTs \in T

8:V{s}V \gets \{s\}

9:Qnew min-priority queueQ \gets \text{new min-priority queue}//Priority queue of edges

10:for (v,w)Adj[s](v, w) \in \text{Adj}[s] do

11:Q.insert((s,v,w))Q.\text{insert}((s, v, w))

12:end for

13:while V<T|V| < |T| do

14:(u,v,w)Q.extract_max()(u, v, w) \gets Q.\text{extract\_max}()//Get max weight edge

15:if vVv \notin V then

16:EE(u,v)E' \gets E' \cup {(u, v)}

17:VVvV \gets V \cup {v}//Mark vv as visited

18:for (x,w)Adj[v](x, w) \in \text{Adj}[v] do

19:if xVx \notin V then

20:Q.insert((v,x,w))Q.\text{insert}((v, x, w))

21:end if

22:end for

23:end if

24:end while

25:return EE'

This is the Prim’s algorithm for finding MSTs. We instead replace the minimum weight with maximum weights to fit with problem description in P1.1

==Correctness:==

Invariant:

  • At L4, invariant holds since and
  • per iteration, we add with the maximum weight edge from any visited nodes to any unvisited node (L6-14). Then add to (L15), maintaining the invariant because:
    • is a maximum weight spanning tree over due to is the maximum weight edge connecting to .

The algorithm never create cycle in since we only add edge from visited nodes to unvisited nodes, which cannot create a cycle.

==Bound function:==

Let be the total weight of edges in . Per iteration, is the maximum possible weight of any spanning tree over the nodes in .

This holds initially when and . Per iteration, we add the maximum weight edge to from to . Bound function is maintained because:

  • Any other spanning tree over must contain an edge from to , and . Therefore,

The loop terminates when , i.e all nodes are visited.

Thus the algorithm is correct.

P1.3

Explain which graph representation you used for your algorithm and what the complexity of your algorithm is using this graph representation.

Uses adjacency list representation of the graph . Since we store a list of edges for each nodes, or for each node , we maintain a list containing the node and weight for every edge .

The time complexity of the algorithm is :

  1. Initialising adjacency list: , where the adjacency list takes to populate
  2. L4: Run for iterations
  3. Inside the loop, find maximum weight edge takes from takes . Therefore each iteration the while loop takes
  4. Adding extracted edge to takes

Thus, the overall time complexity is . If the graph is complete, then , and the time complexity is

The space complexity is

P1.4

What is the worst-case complexity of your solution if you use the other graph representation? Explain your answer

Worst case complexity of the algorithm using adjacency matrix representation is .

If adjacency matrix representation is used, or we use a matrix to represent the graph, where for an edge with weight .

Initialising the matrix will take time.

Adding edges from starting node to priority queue will take time, as we need to scan row which has elements.

Inside the while loop, for loop (L18-23) that iterates over the edges of the newly visited node now takes time, as we need to scane the row that has entries, and for each unvisited node, we insert the edge into which takes time. Therefore, the while loop will take

Thus, the total time complexity would be

Whereas the space complexity is . Could be more efficient for sparse graph where .


Problème 2.

A directed graph with the source and the target is a series-parallel graph if it can be constructed inductively using the following rules:

  1. An elementary series-parallel graph is a single edge from to

  2. The series-construction. Let and be two series-parallel graphs with the node in common (). The graph is a series-parallel graph

  3. The parallel-construction. Let and be two series-parallel graphs without nodes in common () and let be two fresh nodes. The graph is a series-parallel graph.

Now assume we have a series-parallel graph with an edge-weight function (here, are the integers, which includes negative numbers). We note that series-parallel graphs are relatively simple structures.

P2.1

Write an algorithm to compute the single-source shortest paths from the source to all nodes in time

Algorithm 36 ShortestPathsSP(G=(N,E,s,t)\mathcal{G} = (\mathcal{N}, \mathcal{E}, s, t), weightweight)

1:distdist \gets {}//Initialize empty dictionary for distances

2:if G\mathcal{G} is an elementary graph (single edge (s,t)(s,t)) then

3:dist[s]0dist[s] \gets 0

4:dist[t]weight(s,t)dist[t] \gets weight(s,t)

5:else if G\mathcal{G} is a series composition of G1\mathcal{G}_1 and G2\mathcal{G}_2 then

6:dist1ShortestPathsSP(G1,weight)dist_1 \gets ShortestPathsSP(\mathcal{G}_1, weight)

7:dist2ShortestPathsSP(G2,weight)dist_2 \gets ShortestPathsSP(\mathcal{G}_2, weight)

8:distdist1dist2dist \gets dist_1 \cup dist_2//Combine distances

9:for each node nn in G2\mathcal{G}_2 do

10:dist[n]dist[n]+dist1[t1]dist[n] \gets dist[n] + dist_1[t_1]

11:end for

12:else if G\mathcal{G} is a parallel composition of G1\mathcal{G}_1 and G2\mathcal{G}_2 then

13:dist1ShortestPathsSP(G1,weight)dist_1 \gets ShortestPathsSP(\mathcal{G}_1, weight)

14:dist2ShortestPathsSP(G2,weight)dist_2 \gets ShortestPathsSP(\mathcal{G}_2, weight)

15:distdist1dist2dist \gets dist_1 \cup dist_2//Combine distances

16:dist[s]0dist[s] \gets 0

17:dist[t]min(dist1[t1],dist2[t2])dist[t] \gets \min(dist_1[t_1], dist_2[t_2])

18:end if

19:return distdist

P2.2

Explain why your algorithm is correct

Base case: For an elementary graph with one edge , it sets and , which is the shortest path from to .

If is a series-composition: Let and be the two series-parallel graphs with common node .

  • It recursively computes the shortest paths from to all nodes in and , store them in and respectively.
  • For any node , the shortest path from \mu st go through target of . Thus, we update .

If is a parallel-composition: Let and be the two series-parallel graphs with new source and target

  • It recursively computes the shortest paths from to all nodes in and , store them in and respectively.
  • The new source has distance 0, correctly set by
  • The new target has distance , which is the shortest path from to .

In both cases, it combines the distance using union operation, and the algorithm is correct.

P2.3

Explain which graph representation you used for your algorithm and why your algorithm has the stated complexity

It uses adjacency list representation of the graph . Each node maintains a list of its outgoing edges. Since in series-parallel graphs, each node has at most 2 outgoing edges, the adjacency list representation is efficient. Additionally, the algorithm recursively traverse the graph, and finding outgoing edges takes constant time.

For base case, the algorithm takes time to set the distance for the elementary graph.

In both cases, it calls itself on and , taking and time respectively. Then it updates the distance for each node in in time. Thus, the time complexity is

Since each node is visited exactly once during the traversal, the time complexity is (since and )

P2.4

What is the worst-case complexity of your solution if you use the other graph representation? Explain your answer

If using adjacency matrix representation, the worst-case complexity of the algorithm is .

It will take time to initialise the adjacency matrix.

The analysis of the algorithm remains the same. The difference here is that finding outgoing edges for a node will take time in worst-case, as it will have to traverse the entire row of the matrix corresponding to that node. Since the ops is performed on each node during traversal, total complexity would be .