Problem 1 §
Algorithm §
# each item is in format (time, start/end, event_index)
# order priosity: smaller time -> start ->
Q = sort(L, R)
Events = []
while Q has elements:
if Q.next is a start time
t <- Q.dequeue
# if there is a tie in start times
while Q.next.start_time == t.start_time:
t <- max_end_time(t, Q.dequeue)
# t is now the earliest starting time with maximum duration
else Q.next is an end time
# get latest end time
while Q.next is an end time
t <- Q.dequeue
# t is now the latest end time
add t's event to Events
end if
end while
Complexity §
Sorting: O ( n log n )
Loop: O ( n )
⇒ Total: O ( n log n )
Correctness §
Base case
Let Y ∗ = ( y 1 , … ) the optimal solution
Assume Y ∗ ’s y 1 is not the earliest start time……(1)
Algorithm chooses earliest start time x 1 .
[ x 1 . start , y 1 . start ] is in total cover, but not in Y ∗ ’s cover.
This means Y ∗ cannot be optimal. This is a contradiciton
Thus Assumption (1) must be wrong
Inductive Step
Let Y ∗ = ( x 1 … x k − 1 , y k , … ) is the optimal solution
Y ∗ ’s y k is the optimal next choice after x k − 1
Case 1: next item in priority queue is an end time
Algorithm chooses x k where…
x k . start < x k − 1 . end
x k . end < y k + 1 . start
among such points, max ( x k . e n d )
Assume y k is an event that doesn’t satisfy the maximum endtime requirement……(2)
Then, [ y k . end , x k . end ] is in total cover, but not in Y ∗ ’s cover. This is a contradiction.
Thus assumption (2) must be wrong
Case 2: next item in priority queue is a start time
Algorithm chooses x k with the earliest starting time and longest duration
This is at least as optimal as y k , because…
x k . start ≤ y k . start
x k . end ≤ y k . end
Thus the cover of x k is as large as y k
Thus x k is as optimal as y k
QED
Problem 2 §
// Idea: Reverse the order of weights in the graph,
// then run minimum spanning tree.
// First, reverse the weight ordering of the graph
// negate weights...
for e in E
e' <- e
e'.weight <- -e.weight
add e' to E'
let m be the edge with minimum weight in E'
// then monotonically increase so all weights are positive
// (to use MST algorithm)
for e in E'
e'.weight += m.weight + 1
// Then, run MST algorithm (Prim or Kruskal)
V_mst, E_mst <- MST(V, E')
// the minimum spanning tree in (V, E') is
// same as the maximum spanning tree in (V, E)
// Return the edges that are not in the MST.
return E \ E_mst
Correctness §
The problem is equivalent to getting a tree whose sum of edge weights is maximal.
This is because the remaining graph must be acyclic (a tree) and…
…because the sum of removed weights is minimal thus the sum of remaining weights must be maximal.
We can convert the original graph in question to a weight order reversed graph:
Suppose E = { e 1 , e 2 , … , e m } where e i has weight w i
Then, E ′ = { e 1 ′ , … e m ′ } where e i ′ has weight w m − i + 1
Then, we can leverage the correctness of the MST algorithm (prim’s or kruskal’s) in order to get the minimum spanning tree of this new weight-order-reversed-graph.
The edges in this MST is the maximum spanning tree in the original graph
Therefore, removing these edges we are left with the subset F which is minimal
Complexity §
negating weights: O ( m )
monotonically raising weights positive: O ( m )
MST algorith: O ( m log n )
Total: O ( m log n )