Allnotes 25
Allnotes 25
1 / 278
Overview
I. Introduction and getting started
II. Characterizing running time
III. Linear and Divide-and-conquer recurrences
IV. Divide-and-conquer algorithms
V. Greedy algorithms
VI. Dynamic programming
VII. Graph algorithms
VIII. NP-completeness
2 / 278
I. Introduction and Getting Started
3 / 278
Introduction
I Algorithm is a tool for solving a well-specified computational problem
I An algorithm is a well-defined procedure for transforming some input
into a desired output.
I A poem by D. Berlinski in “Advent of the Algorithm”
In the logician’s voice:
an algorithm is
a finite procedure,
written in a fixed symbolic vocabulary
governed by precise instructions,
moving in discrete steps, 1, 2, 3, ...
whose execution requires no insight, cleverness,
intuition, intelligence, or perspicuity
and that sooner or later comes to an end.
4 / 278
Introduction
I Basic questions about an algorithm
1. Does it halt?
2. Is it correct?
3. Is it fast? (Can it be faster?)
4. How much memory does it use?
5. How does data communicate?
5 / 278
Getting started: Example 1
I Fibonacci numbers:
F0 = 0,
F1 = 1,
Fn = Fn−1 + Fn−2 for n≥2
I Fact:
Fibonacci numbers grow almost as fast as the power of 2:
Fn ≈ 20.694n
I Problem statement:
given n, computing the n-th Fibonacci number Fn
6 / 278
Getting started: Example 1
I Recursive algorithm (Algorithm 1) for computing Fn (top-down):
T (n) = T (n − 1) + T (n − 2) + 1
= O(2n ).
7 / 278
Getting started: Example 1
I Iterative algorithm (Algorithm 2) for computing Fn (bottom-up,
memoization):
1. Compute F0 , F1 , F2 , ...., until Fn
2. Running time:
T (n) = T (n − 1) + 1
=n−1
8 / 278
Getting started: Example 1
I Divide-and-conquer algorithm (Algorithm 3) for computing Fn :
1. Reformulation
Fn 0 1 Fn−1
=
Fn+1 1 1 Fn
2
0 1 0 1 Fn−2 0 1 Fn−2
= =
1 1 1 1 Fn−1 1 1 Fn−1
= ···
n
0 1 F0 F0 0
= ≡ Xn = Xn
1 1 F1 F1 1
2. Compute X n by divide-and-conquer
n n
Xn = X 2 · X 2
3. Running time
n
T (n) = T + const.
2
= O(lg n)
9 / 278
Getting started: Example 1
I Approximation algorithm (Algorithm 4) for computing Fn :
10 / 278
Getting started: Example 2
I Problem statement:
Input: a sequence of n numbers ha1 , a2 , . . . , an i
Output: a permutation (reordering) ha01 , a02 , . . . , a0n i of the
a-sequence such that a01 ≤ a02 ≤ · · · ≤ a0n
In short, sorting
11 / 278
Getting started: Example 2
Algorithm 1: Insertion sort
I Idea: incremental approach
12 / 278
Getting started: Example 2
Algorithm 1: Insertion sort
I Pseudocode
InsertionSort(A)
1 n = length(A)
2 for j = 2 to n
3 key = A[j]
4 // insert ‘‘key’’ into sorted array A[1...j-1]
5 i = j-1
6 while i > 0 and A[i] > key do
7 A[i+1] = A[i]
8 i = i-1
9 end while
10 A[i+1] = key
11 end for
12 return A
13 / 278
Getting started: Example 2
Analysis of Algorithm 1: Insertion sort
I Correctness:
argued by induction (“loop-invariant”)
I Complexity (running time):
Define
I T (n) = number of operations for sorting an array of length n,
I tj = number of while-loop executed for j
Then
n
X
T (n) = (1 + 1 + tj + 1)
j=2
n
X
= 3(n − 1) + tj
j=2
14 / 278
Getting started: Example 2
Analysis of Algorithm 1: Insertion sort, cont’d
Xn
I Complexity: T (n) = 3(n − 1) + tj
j=2
I best-case:
tj = 1
T (n) = 4(n − 1) = O(n)
I worst-case:
tj = j
n
X
T (n) = 3(n − 1) + j = O(n2 )
j=2
I average-case:
j
tj =
2
n
X j
T (n) = 3(n − 1) + = O(n2 )
j=2
2
15 / 278
Getting started: Example 2
Analysis of Algorithm 1: Insertion sort, cont’d
I Insertion sort is a “sort-in-place”, no extra memory necessary
I Importance of writing a good pseudocode: “expressing algorithm to
human”
I Homework problem: write a recurisve version of insertion sort.
16 / 278
Getting started: Example 2
Algorithm 2: Merge sort
I Idea: divide-and-conquer approach
17 / 278
Getting started: Example 2
Algorithm 2: Merge sort
I Pseudocode
MergeSort(A,p,r) // Merge-sort of array A[p..r]
1 if p < r then // check for base case
2 q = flooring( (p+r)/2 ) // divide
3 MergeSort(A,p,q) // conquer
4 MergeSort(A,q+1,r) // conquer
5 Merge(A,p,q,r) // combine/merge
6 end if
18 / 278
Getting started: Example 2
Algorithm 2: Merge sort
I Pseudocode, cont’d
Merge(A,p,q,r)
n1 = q-p+1; n2 = r-q
for i = 1 to n1 // create arrays L[1...n1+1] and R[1...n2+1]
L[i] = A[p+i-1]
end for
for j = 1 to n2
R[j] = A[q+j]
end for
L[n1+1] = infty; R[n2+1] = infty // mark the end of arrays L and R
i = 1; j = 1
for k = p to r // Merge arrays L and R to A
if L[i] <= R[j] then
A[k] = L[i]
i = i+1
else
A[k] = R[j]
j = j+1
end if
end for
19 / 278
Getting started: Example 2
Analysis of Algorithm 2: Merge sort
I Merge sort is a divide-and-conquer algorithm consisting of three steps:
divide → conquer → combine
I To sort the entire sequence A[1...n], we make the initial call
MergeSort(A,1,n)
I Complexity:
I Define:
T (n) = number of operations for sorting an array of length n,
I Then
n
T (n) = 1 + 2 · T +n−1
2
= O(n lg(n))
20 / 278
II. Characterizing Running Times
Growth of Functions and Asymptotic Notations
21 / 278
Overview
I Study a way to describe the growth of functions in the limit –
asymptotic efficiency
I Focus on what’s important (leading factor) by abstracting lower-order
terms and constant factors
I Characterize running times of algorithms
I Provide a way to compare “sizes” of functions
O ≈ ≤
Ω ≈ ≥
Θ ≈ =
In addition,
o ≈ <
ω ≈ >
22 / 278
O-notation
3.1 Asymptotic notation
Proof: since
2n + 10 ≤ n2 for n ≥ 5,
therefore, 2n + 10 = O(n2 ) is true for c = 1 and n0 = 5.
24 / 278
More on O-notation
I O(g(n)) is a set of functions
n o
O(g(n)) = f (n) : ∃ c, n0 s.t. 0 ≤ f (n) ≤ cg(n) for n ≥ n0
25 / 278
Ω-notation
3.1 Asymptotic notation 45
f .n/
f .n/ f (n) = Ω(g(n)) f .n/
cg.n/
c g.n/
1
if there exist constants c and n0 such
that
√
n ≥ lg n for n ≥ 16,
Figure 3.1 Graphic examples of the ‚, O, and notations. In each part, the value of n0 shown
√
is the minimum possible value; any greater value would also work. (a) ‚-notation bounds a func-
n = Ω(lg n) is true with c = 1 and
tion to within constant factors. We write f .n/ D ‚.g.n// if there exist positive constants n0 , c1 ,
and c2 n 0 =that
such [Link] and to the right of n0 , the value of f .n/ always lies between c1 g.n/ and c2 g.n/
inclusive. (b) O-notation gives an upper bound for a function to within a constant factor. We write
f .n/ D O.g.n// if there are positive constants n0 and c such that at and to the right of n0 , the value
of f .n/ always lies on or below cg.n/. (c) -notation gives a lower bound for a function to within
a constant factor. We write f .n/ D .g.n// if there are positive constants n0 and c such that at and 26 / 278
More on Ω-notation
I Ω(g(n)) is a set of functions
n o
Ω(g(n)) = f (n) : ∃ c, n0 s.t. 0 ≤ cg(n) ≤ f (n) for n ≥ n0
27 / 278
Θ-notation
3.1 Asymptotic notation
f .n/
f (n) = Θ(g(n))
c1 g.n/
if there exist constants c1 , c2 and n0
such that
Proof: Consider
1 2
c1 n2 ≤ n − 2n ≤ c2 n2
2
i.e.,
1 2
c1 ≤ − ≤ c2 ,
2 n
which is true if we pick
1 1
c1 = , c2 = and n0 = 8.
4 2
d
X
I Lemma. If p(n) = ai ni and ad > 0, then p(n) = Θ(nd ).
i=1
29 / 278
More on Θ-notation
I Θ(g(n)) is a set of functions
Θ(g(n)) =
n o
f (n) : ∃ c1 , c2 , n0 s.t. 0 ≤ c1 g(n) ≤ f (n) ≤ c2 g(n) for n ≥ n0
30 / 278
Theorem
Theorem. O and Ω iff Θ.
31 / 278
Using limits for comparing orders of growth
In order to determine the relationship between f (n) and g(n), it is often
usefuly to examine
f (n)
lim =L
n→∞ g(n)
1. L = 0:
f (n) = O(g(n))
2. L = ∞:
f (n) = Ω(g(n))
3. L 6= 0 is finite:
f (n) = Θ(g(n))
32 / 278
Review: L’Hopital’s rule
L’Hopital’s rule. Let f (x) and g(x) be differential functions with
derivatives f 0 (x) and g 0 (x), respectively, such that
Then
f (x) f 0 (x)
lim = lim 0 .
x→∞ g(x) x→∞ g (x)
33 / 278
Examples for using limits and L’Hopital’s rule
for comparing orders of growth
1. f (n) = n2 and g(n) = n lg n
n2 = Ω(n lg n)
n100 = O(2n )
10n(n + 1) = Θ(n2 )
34 / 278
Reading assignment
Read the textbook to review standard notations and common functions:
4. Logarithms: lg n = log2 n
35 / 278
III. Linear and Divide-and-Conquer Recurrences
36 / 278
Recurrence relations
I A recurrence relation (RR) for the sequence {an } is an equation
that expresses an in terms of one or more of the previous terms of the
sequence, namely, a0 , a1 , . . . , an−1 , for n ≥ n0 , where n0 is a
nonnegative integer.
The initial conditions for a sequence specify the terms that precede the
first term where the RR takes effect.
I Example.
fn = fn−1 + fn−2 for n ≥ 2 with initials f0 = 0 and f1 = 1.
I A sequence {an } is called a solution of a RR if {an } satisfies the RR.
37 / 278
Explicit substitution
For simple RRs, we can find its solution by an explicit substitution.
Examples
1. Find the solution of an = an−1 + 3 with a1 = 2.
38 / 278
Linear recurrence relations
I A linear kth-order recurrence relation with constant coefficients is of
the form
where
I c1 , c2 , . . . ck are constants (do not depend on n),
I ck =6 0,
I f (n) is a function of n.
If f (n) = 0, then the relation is also called to be homogeneous.
Otherwise, it is called nonhomogeneous.
39 / 278
Linear recurrence relations
I A linear second-order homogeneous linear recurrence relation
with constant coefficients is a recurrence relation of the form
r2 − c1 r − c2 = 0.
Then
I if r1 6= r2 , then the solution of the RR (1) is given by
an = αr1n + βr2n ,
I if r1 = r2 , then the solution of the RR (1) is given by
an = αr1n + βnr1n ,
41 / 278
Divide-and-Conquer recurrences
I Divide-and-Conquer (DC) recurrence:
n
T (n) = a · T + f (n)
b
where
I constants a ≥ 1 and b > 1,
I function f (n) is nonnegative, f (n) ≥ 0.
I Example. the cost function of Merge Sort
n
T (n) = 1 + 2 · T + (n − 1)
2
where
I a = 2 (the number of subproblems)
I b = 2 (n/2 is the size of subproblems)
I f (n) = 1 + (n − 1) = n (the cost to divide and combine)
for simplicity, assuming n = 2k for k ≥ 1.
42 / 278
Two methods for finding solutions of DC recurrences
1. Explicit substitution/recursion
2. The master theorem/method
43 / 278
Solving DC recurrences by explicit substitution
I Explicit substitution can be illustrated by the following example
n
T (n) = 4 · T + n, n = 2k
2
I By iterating the recurrence (i.e. explicit substitution), we have
n
T (n) = 4 · T +n
2 n
n n
2
= 4 · 4 · T( ) + + n = 42 · T ( 2 ) + 2n + n
2 2 2
n
3 2
=4 ·T + 2 n + 2n + n
23
= ···
n
= 4k · T + 2k−1 n + · · · + 2n + n
2k
= 4k · T (1) + (2k−1 + · · · + 2 + 1)n
k
2 −1
= 4k · T (1) + n = n2 · T (1) + n(n − 1) = Θ(n2 )
2−1
44 / 278
The master theorem/method to solve DC recurrences
I For the DC recurrence, let n = bk , then by substitution1 , we have
k−1
X n
T (n) = nlogb a · T (1) + aj f
j=0
bj
nlogb a
= Ω(n ) for some constant > 0,
f (n)
then
T (n) = Θ(nlogb a ).
46 / 278
The master theorem/method to solve DC recurrences
Case 2: If nlogb a and f (n) are on the same order, i.e.,
f (n) = Θ(nlogb a ),
then
T (n) = Θ(nlogb a lg n).
47 / 278
The master theorem/method to solve DC recurrences
Case 3: If f (n) is polynomially greater than nlogb a , i.e.,
f (n)
= Ω(n ) for some constant > 0
nlogb a
and f (n) satisfies the regularity condition (see next slide),
then
T (n) = Θ(f (n)).
Example. T (n) = 4 · T ( n2 ) + n3
48 / 278
Remarks
1. f (n) satisfies the regularity condition if
n
a·f ≤ cf (n)
b
for some constant c < 1 and for all sufficient large n.
2. The proof of the master theorem is involved, shown in section 4.6,
which we can safely skip.
3. The master theorem doesn’t cover all possible cases, and the master
method cannot solve every DC recurrences.
49 / 278
IV. Divide-and-Conquer Algorithms
50 / 278
Divide-and-Conquer algorithms – Overview
The Divide-and-Conquer (DC) strategy solves a problem by
Recall that MergeSort (in Part I) served as the first example of the DC
algorithm paradigm. In addition, in Homework 1, we have also explored the
DC strategy for finding min and max, ...
51 / 278
The maximum-subarray problem
Problem statement:
Input: an array A[1...n] of (positive/negative) numbers.
Output:
(1) Indices i and j such that the subarray A[i...j] has the
greatest sum of any nonempty contiguous subarray of A
(2) the sum of the values in A[i...j].
Note: Maximum subarray might not be unique, though its value is, so we
speak of a maximum subarray, rather than the maximum subarray.
52 / 278
The maximum-subarray problem
Example 1: stock prices and changes
Day 0 1 2 3 4
Price 10 11 7 10 6
A[...] (change) 1 -4 3 -4
maximum-subarray: A[3] (i = j = 3) and Sum = 3
53 / 278
The maximum-subarray problem
Example 3: stock prices and changes
54 / 278
The maximum-subarray problem
Algorithm 1. Solve by brute-force
I Check all subarrays A[i...j]
I Total number of subarrays A[i...j]:
n n! 1
= = n(n − 1) = Θ(n2 )
2 2!(n − 2)! 2
55 / 278
The maximum-subarray problem
Algorithm 2. Solve by Divide-and-Conquer
I Generic problem:
Find a maximum subarray of A[low...high]
with initial call: low = 1 and high = n
I DC strategy:
56 / 278
The maximum-subarray problem
I Possible locations of max subarrays:
I Correctness: This strategy works because any subarray must either lie
entirely in one side of midpoint or cross the midpoint.
57 / 278
The maximum-subarray problem
MaxSubarray(A,low,high)
if high == low // base case: only one element
return (low, high, A[low])
else
// divide
mid = floor( (low + high)/2 )
// conquer
(leftlow,lefthigh,leftsum) = MaxSubarray(A,low,mid)
(rightlow,righthigh,rightsum) = MaxSubarray(A,mid+1,high)
(xlow,xhigh,xsum) = MaxXingSubarray(A,low,mid,high)
// combine
if leftsum >= rightsum and leftsum >= xsum
return (leftlow,lefthigh,leftsum)
else if rightsum >= leftsum and rightsum >= xsum
return (rightlow,righthigh,rightsum)
else
return (xlow,xhigh,xsum)
end if
end if
58 / 278
The maximum-subarray problem
MaxXingSubarray(A,low,mid,high)
leftsum = -infty; sum = 0 // Find max-subarray of A[i..mid]
for i = mid downto low
sum = sum + A[i]
if sum > leftsum
leftsum = sum
maxleft = i
end if
end for
rightsum = -infty; sum = 0 // Find max-subarray of A[mid+1..j]
for j = mid+1 to high
sum = sum + A[j]
if sum > rightsum
rightsum = sum
maxright = j
end if
end for
// Return the indices i and j and the sum of two subarrays
return (maxleft,maxright,leftsum+rightsum)
59 / 278
The maximum-subarray problem
Remarks:
1. Initial call: MaxSubarray(A,1,n)
2. Base case is when the subarray has only 1 element.
3. Divide by computing mid.
Conquer by the two recursive calls to MaxSubarray. and a call to
MaxXingSubarray
Combine by determining which of the three results gives the maximum
sum.
4. Complexity:
n
T (n) = 2 · T + Θ(n) + Θ(1)
2
= Θ(n lg n)
60 / 278
Matrix-matrix multiplication: Strassen’s method
I Problem statement:
Given n × n matrices A and B, compute the product
C =A·B
61 / 278
Matrix-matrix multiplication: Strassen’s method
I Traditional method: (i, j, k)-triple-loop
for i = 1 to n
for j = 1 to n
C(i,j) = 0
for k = 1:n
C(i,j) = C(i,j) + A(i,k)*B(k,j)
end
end
end
I Complexity:
n
X Xn X
n
T (n) = 2 = 2n3 = Θ(n3 )
i=1 j=1 k=1
62 / 278
Matrix-matrix multiplication: Strassen’s method
I Divide-and-conquer: a naive implementation
2. Complexity:
n
T (n) = 8 · T ( ) + Θ(n2 ) = Θ(n3 )
2
Same cost as the traditional method, No improvement!
63 / 278
Matrix-matrix multiplication: Strassen’s method
I Strassen’s divide-and-conquer method (Strassen’s method) reduces the
complexity to
T (n) = Θ(nlg 7 ) = Θ(n2.8074.... ).
I Reference:
V. Strassen, Gaussian elimination is not optimal. Numer. Math.
Vol.13, pp.354-356, 1969
I The subsequent improvements, with the current world record2 being
O(n2.3728596 ), are much more complicated (and astonishing), but less
practical.
65 / 278
Matrix-matrix multiplication: Strassen’s method
I Strassen’s method – Step 2:
Compute 10 matrices by + or − operations only:
S1 = B12 − B22
S2 = A11 + A12
S3 = A21 + A22
S4 = B21 − B11
S5 = A11 + A22
S6 = B11 + B22
S7 = A12 − A22
S8 = B21 + B22
S9 = A11 − A21
S10 = B11 + B12
66 / 278
Matrix-matrix multiplication: Strassen’s method
I Strassen’s method – Step 3:
Compute 7 matrices by multiplication:
P1 = A11 · S1
P2 = S2 · B22
P3 = S3 · B11
P4 = A22 · S4
P5 = S5 · S6
P6 = S7 · S8
P7 = S9 · S10
67 / 278
Matrix-matrix multiplication: Strassen’s method
I Strassen’s method – Step 4:
Add and subtract Pi to construct submatrices Cij of the product C:
C11 = P5 + P4 − P2 + P6
C12 = P1 + P2
C21 = P3 + P4
C22 = P5 + P1 − P3 − P7
68 / 278
Matrix-matrix multiplication: Strassen’s method
I Correctness: straightfoward verification
69 / 278
The closest pair of points
Problem statement:
Given a set of n points on a line (1-dimensional, unsorted), find
two points whose distance is shortest.
Remark:
I The problem is known as the closest pair problem in 1-dimension.
There is an algorithm for finding the closest pair of points in
2-dimension, i.e., on a plane, by extending the DC strategy we discuss
here.
70 / 278
The closest pair of points
A brute-force solution
I Pick two of n points and compute the distance
I Cost:
n n!
T (n) = = = Θ(n2 ).
2 2!(n − 2)!
71 / 278
The closest pair of points
I Algorithm 1
I Cost:
Θ(n lg n) + Θ(n) = Θ(n lg n)
I Unfortunately, the algorithm cannot be extended to the 2-dimension
case.
72 / 278
The closest pair of points
I Algorithm 2 (Divide-and-Conquer):
1. Divide the set S of n points by some point mid ∈ S into two sets S1
and S2 such that
73 / 278
The closest pair of points
Remarks:
1. Both p3 and q3 must be within distance d = min{|p1 − p2 |, |q1 − q2 |}
of mid if {p3 , q3 } is to have a distance smaller than d.
2. How many points of S1 can lie in (mid − d, mid]?
answer: at most one
3. How many points of S2 can lie in [mid, mid + d)?
answer: at most one
4. Therefore, the number of pairwise comparisons that must be made
between points in different subsets is thus at most one.
74 / 278
The closest pair of points
Pseudocode of Algorithm 2 (Divide-and-Conquer)
ClosestPair(S)
if |S| = 2, then
d = |S[2] - S[1]|
else
if |S| = 1
d = infty
else
mid = median(S)
construct S1 and S2 from mid
d1 = ClosestPair(S1)
d2 = ClosestPair(S2)
p3 = max(S1)
q3 = min(S2)
d = min(d1, d2, q3-p3)
end if
end if
return d
75 / 278
The closest pair of points
Remark:
1. A median of a set A is the “halfway point” of the set A can be found
in linear time Θ(n) on average (see Chapter 9).
2. The points in the intervals (mid − d, mid] and [mid, mid + d) can be
found in linear time O(n), called linear scan.
3. Total cost:
n
T (n) = 2 · T ( ) + Θ(n)
2
= Θ(n lg n).
76 / 278
Extra: Medians and order statistics
I Selection problem:
Input:
A set A of n (distinct) numbers and an integer i, with 1 ≤ i ≤ n.
Output:
The element x ∈ A that is larger than exactly i − 1 other elements
of A. In other words, x is the ith smallest element of A.
I A median is the “halfway point” of the set A, i.e, i = d(n + 1)/2e.
I A simple sorting algorithm will take O(n lg n) time.
I Yet, a DC strategy leads to running time of O(n).
77 / 278
V. Greedy Algorithms
78 / 278
Greedy algorithms – Overview
I Algorithms for solving (optimization) problems typically go through a
sequence of steps, with a set of choices at each step.
I A greedy algorithm always makes the choice that looks best at the
moment, without regard for future consequence, i.e., “take what you
can get now” strategy
Local optimum =⇒
? Global optimum
79 / 278
Activity-selection problem
Problem statement:
Remarks:
I Activities i and j are compatible if the intervals [s[i], f [i]) and
[s[j], f [j]) do not overlap.
I Without loss of generality, assume
80 / 278
Activity-selection problem
Example
i s[i] f [i]∗
1 1 4
2 3 5
3 0 6
4 5 7
5 3 8
6 5 9
7 6 10
8 8 11
9 8 12
10 2 13
11 12 14
*Note that f [i] are sorted
81 / 278
Activity-selection problem
Greedy algorithm:
I pick the compatible activity with the earliest finish time.
Why?
I Intuitively, this choice leaves as much opportunity as possible for the
remaining activities to be scheduled
I That is, the greedy choice is the one that maximizes the amount of
unscheduled time remaining.
82 / 278
Activity-selection problem
I Pseudocode
Greedy_Activity_Selector(s,f)
// the array f already sorted
n = length(s)
A = {1}
j = 1
for i = 2 to n
if s[i] >= f[j]
A = A U {i}
j = i
end if
end for
return A
83 / 278
Activity-selection problem
Example
Pseudocode
i s[i] f [i]
1 1 4 Greedy_Activity_Selector(s,f)
2 3 5 n = length(s)
3 0 6 A = {1}
4 5 7 j = 1
5 3 8 for i = 2 to n
6 5 9 if s[i] >= f[j]
7 6 10 A = A U {i}
8 8 11 j = i
9 8 12 end if
10 2 13 end for
11 12 14 return A
84 / 278
Activity-selection problem
Question: Does Greedy Activity Selector work?
Answer: Yes!
85 / 278
Activity-selection problem
The proof of Theorem is based on the following two properties:
Property 1.
There exists an optimal solution A such that the greedy choice “1”
in A.
Proof:
I let’s order the activities in A by finish time such that the first
activity in A is k1 .
I If k1 = 1, then A begins with a greedy choice
I If k1 6= 1, then let A0 = (A − {k1 }) ∪ {1}.
Then
1. the sets A − {k1 } and {1} are disjoint
2. the activities in A0 are compatible
3. A0 is also optimal, since |A0 | = |A|
I Therefore, we conclude that there always exists an optimal
solution that begins with a greedy choice.
86 / 278
Activity-selection problem
Property 2.
If A is an optimal solution, then A0 = A−{1} is an optimal solution
to S 0 = {i ∈ S, s[i] ≥ f [1]}.
Proof: By contradiction. If there exists B 0 to S 0 such that |B 0 | >
|A0 |, then let
B = B 0 ∪ {1},
we have
|B| > |A|,
which is contradicting to the optimality of A.
87 / 278
Activity-selection problem
Proof of Theorem: By Properties 1 and 2, we know that
I After each greedy choice is made, we are left with an optimization
problem of the same form as the original.
I By induction on the number of choices made, making the greedy
choice at every step proceduces an optimal solution.
Therefore, the Greedy Activity Selector produces an optimal solution
of the activity-selection problem.
88 / 278
Activity-selection problem
I Property 1 is called the greedy-choice property, generally casted as
a globally optimal solution can be arrived at by making a locally
optimal (greedy) choice.
These are two key properties for the success of greedy algorithms!
89 / 278
Huffman codes
I Used for data compression, typically saving 20%–90%
I Basic idea:
represent often encountered characters by shorter (binary) codes
90 / 278
Huffman codes
Example
I Suppose we have the following data file with total 100 characters:
Character a b c d e f
Frequency 45 13 12 16 9 5
3-bit fixed length code 000 001 010 011 100 101
variable length code 0 101 100 111 1101 1100
91 / 278
Huffman codes
Prefix(-free) codes:
1. No codeword is also a prefix3 of some other code.
2. Example. A prefix code
Char. a b c d e f
Code 0 101 100 111 1101 1100
I Decode:
I 101110111011100 −→ beef
I 110001001101 −→ face
93 / 278
Huffman codes
5. Example, cont’d
Character a b c d e f
Frequency 45 13 12 16 9 5
3-bit fixed length code 000 001 010 011 100 101
variable length code 0 101 100 111 1101 1100
94 / 278
Huffman codes
Let C = set of characters/alphabets, then
I A code = a binary tree T
I For each character c ∈ C, define
95 / 278
Huffman codes
Let C = set of characters/alphabets, then the basic idea of Huffman codes
to produce a prefix code for C:
represent often encountered characters by shorter (binary) codes
via
1. Building a full binary tree T in a bottom-up manner
2. Beginning with |C| leaves, performs a sequence of |C| − 1 “merging”
operations to create T
3. “Merging” operation is greedy: the two with lowest frequencies are
merged.
96 / 278
Review: data structure:priority queue
I A priority queue is a data structure for maintaining a set S of
elements, each with an associated key.
I A min-priority queue supports the following operations:
I Insert(S,x): inserts the element x into the set S, i.e., S = S ∪ {x}.
I Minimum(S): returns the element of S with the smallest “key”.
I ExtractMin(S): removes and returns the element of S with the
smallest “key”.
I DecreaseKey(S,x,k): decreases the value of element x’s key to the new
value k, which is assumed to be at least as small as x’s current key
value.
I A max-priority queue supports the operations:
Insert(S, x), Maximum(S), ExtractMax(S), IncreaseKey(S, x, k).
I Section 6.5 describes a binary heap implementation.
I Cost: let n = |S|, then
I initialization building heap = O(n)
I each heap operation = O(lg n)
97 / 278
Huffman codes
Pseudocode:
Huffmancode(C)
n = |C|
Q = C // min-priority queue, keyed by freq attribute
for i = 1 to n-1
allocate a new node z
z_left = x = ExtractMin(Q)
z_right = y = ExtractMin(Q)
freq[z] = freq[x] + freq[y]
Insert(Q,z)
endfor
return ExtractMin(Q) // the root of the tree
98 / 278
Huffman codes
Example
99 / 278
Huffman codes
Running time:
100 / 278
Huffman codes
Optimality:
To prove the greedy algorithm Huffmancode producing an optimal prefix
code, we show that it exhibits the following two ingradients:
1. The greedy-choice property
If x, y ∈ C having the lowest frequencies, then there exists an optimal
code T such that
I dT (x) = dT (y)
I the codes for x and y differ only in the last bit
101 / 278
Huffman codes
By the above two properties, after each greedy choice is made, we are left
with an optimization problem of the same form as the original. By
induction, we have
102 / 278
Greedy algorithms – Recap
I A greedy algorithm makes the choice that looks best at the moment,
without regard for future consequence
I Greedy algorithms do not always yield optimal solutions, but for many
problems they do.
103 / 278
Knapsack problem
Problem statement:
I Given n items {1, 2, . . . , n}, and item i is worth vi and weight wi
I Given a total allowable weight W
I Find a most valuable subset of items with total weight ≤ W
Rule: have to either take an item or not take it cannot take part of it (“0-1
Knapsack”).
Example: Given
i vi wi vi /wi
1 6 1 6
2 10 2 5
3 12 3 4
Total weight W = 5
Find a most valuable subset of items with total weight ≤ W = 5
104 / 278
Knapsack problem
Problem statement, mathematically – version 1:
Find a subset S ⊆ {1, 2, . . . , n} such that
X
maximize vi
i∈S
X
subject to wi ≤ W
i∈S
105 / 278
Knapsack problem
Problem statement, mathematically – version 2:
Let x = (x1 , x2 , . . . , xn ), and
1 i-th item is in the knapsack
xi =
0 i-th item is not in the knapsack
106 / 278
Knapsack problem
The brute-force algorithm
I 2n feasible solutions
I Total cost = O(n · 2n )
107 / 278
Knapsack problem
Three possible greedy strategies:
vi
3. Greedy by largest value density
wi
108 / 278
Knapsack problem
Example 1. Consider
i vi wi vi /wi
1 6 1 6
2 10 2 5
3 12 3 4
Total weight W = 5
Greedy by value density vi /wi : Optimal solution
I take items 1 and 2. I take items 2 and 3.
I value = 16, weight = 3 I value = 22, weight = 5
I Leftover capacity = 2 I no leftover capacity
109 / 278
Knapsack problem
Example 2. Given the following six items with W = 100:
Greedy by
i vi wi vi /wi value weight vi /wi
1 40 100 0.4 1 0 0
2 35 50 0.7 0 0 1
3 18 45 0.4 0 1 0
4 4 20 0.2 0 1 1
5 10 10 1 0 1 1
6 2 5 0.4 0 1 1
Total value 40 34 51
Total weight 100 80 85
All three greedy approaches generate feasible solutions, but none of them
generate the optimal solution:
Take items 2, 3 and 6, yield total value = 55, and total weight = 100.
Conclusion: Greedy algorithms doesn’t work for the knapsack problem!
110 / 278
VI. Dynamic Programming
111 / 278
Dynamic Programming – Overview
I Not a specific algorithm, but a technique like Divide-and-Conquer and
Greedy algorithms
I Developed back in the day (1950s) when “programming” meant
“tabular method”
I Used for optimization problems
I Find a solution with the optimal value
I Minimization or maximization
112 / 278
Dynamic Programming
Four-step (two-phase) method:
1. Characterize the structure of an optimal solution
2. Recursively define the value of an optimal solution
3. Compute the value of an optimal solution in a bottom-up fashion
4. Construct an optimal solution from computed information
113 / 278
The rod cutting problem
Problem statement:
I Input:
1) a rod of length n
2) an array of prices pi for a rod of length i for i = 1, . . . , n.
I Output:
1) the maximum revenue rn obtainable for a rod of length n
2) optimal cut
In short,
How to cut a rod into pieces in order to maximize the revenue you
can get?
114 / 278
The rod cutting problem
Example
rod length i 1 2 3 4 5 6 7 8 9 10
price pi 1 5 8 9 10 17 17 20 24 30
ri 1 5 8 10 13 17 18 22 25 30
si 1 2 3 2 2 6 1 2 3 10
115 / 278
The rod cutting problem
A brute-force solution:
cut up a rod of length n in 2n−1 different ways (because can choose
to cut or not cut after each of the first n − 1 inchies)
Cost: Θ(2n−1 )
rod length i 1 2 3 4
Example. Given
price pi 1 5 8 9
There are 24−1 = 8 possible ways to cutting a rod of length 4:
116 / 278
The rod cutting problem
Dynamic Programming – Phase I:
I Since every optimal solution rn has a leftmost cut with length i, the
optimal revenue rn is given by
where
117 / 278
The rod cutting problem
Dynamic Programming – Phase II:
I How to compute rn by the expression (2)
I Recursive solution:
I top-down
I Calling graph
with T (0) = 1.
Solution: T (n) = Θ(2n ).
118 / 278
The rod cutting problem
Dynamic Programming – Phase II:
I How to compute rn by the expression (2), cont’d
I Iterative solution
I bottom-up (memoization) (Pseudocode – see next page)
I Calling graph
119 / 278
The rod cutting problem
cut-rod(p,n)
// an iterative (bottom-up) procedure for finding ‘‘r’’ and
// the optimal size of the first piece to cut off ‘‘s’’
Let r[0...n] and s[0...n] be new arrays
r[0] = 0
for j = 1 to n
// find q = max{p[i]+r[j-i]} for 1 <= i <= j
q = -infty
for i = 1 to j
if q < p[i] + r[j-i]
q = p[i] + r[j-i]
s[j] = i
end if
end for
r[j] = q
end for
return r and s
120 / 278
The rod cutting problem
Example
rod length i 1 2 3 4 5 6 7 8 9 10
price pi 1 5 8 9 10 17 17 20 24 30
ri 1 5 8 10 13 17 18 22 25 30
si 1 2 3 2 2 6 1 2 3 10
121 / 278
Matrix-chain multiplication
Review: Matrix-matrix multiplication
I Given A of order p × q and B of order q × r, then
C = AB is of order p × r
122 / 278
Matrix-chain multiplication
Review: ordering of matrix-chain multiplication
I Given A1 : p0 × p1 , A2 : p1 × p2 and A3 : p2 × p3 , then different
orderings of the product A1 A2 A3 generate the same result, i.e.,
123 / 278
Matrix-chain multiplication
Problem statement:
124 / 278
Matrix-chain multiplication
Brute-force solution
I Exhaustive search for determining the optimal ordering
I Counting the total number of orderings
1. Define
P (n) = the number of orderings for a chain of n matrices
2. Then
P (1) = 1
P (n) = P (1)P (n − 1) + P (2)P (n − 2) + · · · + P (n − 1)P (1)
n−1
X
= P (k)P (n − k) for n ≥ 2,
k=1
125 / 278
Matrix-chain multiplication
DP – step 1: characterize the structure of an optimal ordering
I An optimal ordering of the product A1 A2 · · · An splits the product
between Ak and Ak+1 for some k:
A1 A2 · · · An = A1 · · · Ak · Ak+1 · · · An
| {z } | {z }
I Key observation:
I Within this (“global”) optimal ordering of A1 · · · An must be an
optimal ordering of (sub-product) A1 · · · Ak .4
I Similar observation holds for Ak+1 · · · An
I Thus, an optimal (“global”) solution contains within it the optimal
(“local”) solutions to subproblems.
4 Why? simply argue by contradiction: If there was a less costly way to order the
product A1 · · · Ak , substituting that ordering within this (global) optimal ordering would
produce another ordering of A1 A2 · · · An , whose cost would be less than the optimum, a
contradiction!
126 / 278
Matrix-chain multiplication
DP – step 2: recursively define the value of an optimal solution
I Define
127 / 278
Matrix-chain multiplication
DP – step 3: compute the value of an optimal solution in a bottom-up
approach
I Compute m[i, j] and s[i, j] in a bottom-up approach (see the
pseudocode in next page)
128 / 278
Matrix-chain multiplication
matrix-chain-order(p)
create m[1...n,1...n] and s[1...n,1...n] and n = length(p)-1
for i = 1 to n
m[i,i] = 0
for d = 2 to n
for i = 1 to n-d+1
j = i + d - 1
m[i,j] = +infty //compute m[i,j]=min_k{...}
for k = i to j-1
q = m[i,k] + m[k+1,j] + p[i-1]*p[k]*p[j]
if q < m[i,j]
m[i,j] = q
s[i,j] = k
endif
endfor
endfor
endfor
return m and s
129 / 278
Matrix-chain multiplication
DP – step 4: construct an optimal solution from computed m and s tables
130 / 278
Matrix-chain multiplication
Example 1. Let p = [10 5 10 5], then A1 : 10 × 5, A2 : 5 × 10,
A3 : 10 × 5
matrix-chain-order(p) generates the following m-table for optimal
costs, and s-table for orderings:
m = [ 0 500 500 ] s = [ 0 1 1 ]
[ 0 0 250 ] [ 0 0 2 ]
[ 0 0 0 ] [ 0 0 0 ]
132 / 278
Matrix-chain multiplication
Example 2, cont’d
matrix-chain-order(p) generates the following m-table for optimal
costs, and s-table for orderings:
m = [ 0 12 35 52 ] s = [ 0 1 1 1 ]
[ 0 0 20 40 ] [ 0 0 2 3 ]
[ 0 0 0 80 ] [ 0 0 0 3 ]
[ 0 0 0 0 ] [ 0 0 0 0 ]
m[1,4] = 52
By s-table, an optimal parenthesization (ordering) of the matrix-chain
multiplication is given by
( A1 )( ( A2 A3 ) A4 )
133 / 278
Matrix-chain multiplication
Example 3. Let p = [30 35 15 5 10 20 25].
( A1 ( A2 A3 ) ) ( ( A4 A5 ) A6 )
134 / 278
Longest Common Subsequence (LCS)
Problem statement:
Input: Sequences
Xm = hx1 , x2 , x3 , . . . , xm i
Yn = hy1 , y2 , . . . , yn i
135 / 278
LCS: terminology
1. Sequence: an order list of elements, e.g.
I X7 = hA, B, C, B, D, A, Bi
I Y6 = hB, D, C, A, B, Ai
I algorithm
2. Subsequence, e.g.
I hA, C, D, Bi is a subsequence of X7
I hB, C, Ai is a subsequence of Y6
I art is a subsequence of algorithm
136 / 278
LCS
A brute-force solution:
I For every subsequence of Xm , check if it is a subsequence of Yn .
I Intractable!
137 / 278
LCS
DP – step 1: characterize the structure of an optimal solution
Let Zk = hz1 , z2 , . . . , zk i be any LCS of
Then
I Case 1: xm = yn
(a) zk = xm = yn and
(b) Zk−1 = hz1 , z2 , . . . , zk−1 i = LCS(Xm−1 , Yn−1 )
I Case 2: xm 6= yn
(a) zk 6= xm =⇒ Zk = LCS(Xm−1 , Yn ) and
(b) zk 6= yn =⇒ Zk = LCS(Xm , Yn−1 )
In words, the optimal solution to the (whole) problem contains within it the
otpimal solutions to subproblems = the optimal substructure property
138 / 278
LCS
DP – step 2: recursively define the value of an optimal solution
I Define
c[i, j] = length of LCS(Xi , Yj )
for i = 0, 1, . . . , m and j = 0, 1, . . . , n
I c[m, n] = length of LCS(Xm , Yn )
I initialization: c[i, 0] = c[0, j] = 0
139 / 278
LCS
I In summary
for i = 0, 1, . . . , m and j = 0, 1, . . . , n,
0 if i = 0 or j = 0 (initials)
c[i, j] = c[i − 1, j − 1] + 1 if x[i] = y[j] (Case 1)
max{c[i, j − 1], c[i − 1, j]} if x[i] = 6 y[j] (Case 2)
140 / 278
LCS
DP – step 3: compute c[i, j] (and b[i, j]) in a bottom-up approach
I Compute c[i, j] and b[i, j] in a bottom-up approach, see pseudocode.
I c[i, j] is the length of LCS(Xi , Yj )
I b[i, j] shows how to construct the corresponding LCS(Xi , Yj )
I Cost:
I Running time: Θ(mn)
I Space: Θ(mn)
141 / 278
LCS
LCS-length(X,Y)
set c[i,0] = 0 for i = 0,1,...,m and c[0,j] = 0 for j = 0,1,...,n
for i = 1 to m // Row-major order to compute c and b tables
for j = 1 to n
if X(i) = Y(j)
c[i,j] = c[i-1,j-1] + 1
b[i,j] = ’Diag’ // go to up diagonal
elseif c[i-1,j] >= c[i,j-1]
c[i,j] = c[i-1,j]
b[i,j] = ’Up’ // go up
else
c[i,j] = c[i,j-1]
b[i,j] = ’Left’ // go left
endif
endfor
endfor
return c and b
142 / 278
LCS
DP – step 4: construct an optimal solution from computed information
143 / 278
LCS
15.4 Longest common subsequence
Example: X7 = hA, B, C, B, D, A, Bi and Y6 = hB, D, C, A, B, Ai
c[·, ·] + b[·, ·] : j 0 1 2 3 4 5 6
i yj B D C A B A
0 xi 0 0 0 0 0 0 0
1 A 0 0 0 0 1 1 1
2 B 0 1 1 1 1 2 2
3 C 0 1 1 2 2 2 2
4 B 0 1 1 2 2 3 3
5 D 0 1 2 2 2 3 3
6 A 0 1 2 2 3 3 4
7 B 0 1 2 2 3 4 4
145 / 278
Knapsack problem revisited
Greedy solution strategy: three possible greedy approaches:
vi
3. Greedy by largest value density
wi
146 / 278
Knapsack problem revisited
Example 1:
i vi wi vi /wi
1 6 1 6
2 10 2 5
3 12 3 4
Total weight W = 5
Greedy by value density vi /wi :
I take items 1 and 2.
I value = 16, weight = 3
I Leftover capacity = 2
Optimal solution – by inspection
I take items 2 and 3.
I value = 22, weight = 5
I no leftover capacity
See Homework 4 for a large example.
147 / 278
Knapsack problem revisited
The knapsack problem exhibits the optimal substructure property:
S = {i1 , . . . , ik−1 , ik },
Then
1. S 0 = S − {ik } is an optimal solution for weight W − wik
and items {i1 , . . . , ik−1 }
2. the value of the optimal solution S is
148 / 278
Knapsack problem revisited
I Define
c[i, w] = value of an optimal solution for items {1, . . . , i}
and maximum weight w.
I Then we have the following two cases for the item i > 0:
I Case 1 (wi > w): the weight of item i is larger than the weight limit
w, then item i cannot be included, and
c[i, w] = c[i − 1, w]
I Case 2 (wi ≤ w): we have two choices:
I choice 1: includes item i, in which case it is vi plus a subproblem
solution for i − 1 items and the weight excluding wi :
I choice 2: does not include item i, in which case it is a subproblem
solution of i − 1 items and the same weight:
150 / 278
Knapsack problem revisited
I The set of items to take can be deduced from the c-table by starting
at c[n, W ] and tracing where the optimal values came from as follows:
I If c[i, w] = c[i − 1, w], item i is not part of the solution, and we
continue tracing with c[i − 1, w].
I If c[i, w] 6= c[i − 1, w], item i is part of the solution, and we continue
tracing with c[i − 1, w − wi ].
151 / 278
Knapsack problem revisited
Example 1.
i vi wi vi /wi
1 6 1 6
2 10 2 5
3 12 3 4
Total weight W = 5
By dynamic programming, we generate the following c-table:
i\w 0 1 2 3 4 5
0 0 0 0 0 0 0
1 0 6 6 6 6 6
2 0 6 10 16 16 16
3 0 6 10 16 18 22
By the c-table, we have
I Optimal value = c[3, 5] = 22.
I The optimal solution (the items to take): S = {3, 2}
152 / 278
Knapsack problem revisited
Example 2: We have n = 9 items with
I value = v = [2, 3, 3, 4, 4, 5, 7, 8, 8]
I weight = w = [3, 5, 7, 4, 3, 9, 2, 11, 5]
I Total allowable weight W = 15
153 / 278
Dynamic Programming – Summary
I Not a specific algorithm, but a technique
(like Divide-and-Conquer and Greedy algorithms)
I Four-step (two-phase) technique:
1. Characterize the structure of an optimal solution
2. Recursively define the value of an optimal solution
3. Compute the value of an optimal solution in a bottom-up fashion
4. Construct an optimal solution from computed information
154 / 278
Dynamic Programming – Summary
Three Key Elements of DP:
1. Optimal substructure:
the optimal solution to the problem contains optimal solutions to
subprograms =⇒ recursive algorithm
Example: Recursive formulation of LCS
2. Overlapping subproblems:
There are few subproblems in total, and many recurring instances
of each. (unlike divide-and-conquer, where subproblems are inde-
pendent)
Example: mn distinct subproblems of LCS
3. Memoization:
after computing solutions to subproblems, store in table, subse-
quent calls do table lookup.
Example: Θ(mn) running time for finding LCS
155 / 278
VII. Graph Algorithms
156 / 278
Graph algorithms – Outline
Part I
1. Notion of graphs
2. Breadth-first search
3. Depth-first search
4. Topological sort
Part II
157 / 278
Notion of graphs
I Graph G = (V, E):
I V = {vi } = set of vertices
I E = set of edges = a subset of V × V = {(vi , vj )}
I |E| = O(|V |2 )
I dense graph: |E| ≈ |V |2
I sparse graph: |E| ≈ |V |
I If G is connected, then |E| ≥ |V | − 1.
I Some variants
I undirected: edge (u, v) = edge (v, u)
I directed: (u, v) is an edge from u to v.
I weighted: weight on either edge or vertex
I multigraph: multiple edges between vertices
158 / 278
Notion of graphs
Representing a graph G by an Adjacency List
I For each vertex vi
159 / 278
Notion of graphs
Example 1: undirected graph
160 / 278
Notion of graphs
Representing a graph G by an Adjacency Matrix A
I A = (aij ) is a |V | × |V | matrix, where
1, if (vi , vj ) ∈ E
aij =
0, otherwise
161 / 278
Notion of graphs
Representing a graph G with no self-loops by an Incidence Matrix B
I If G is undirected, B = (bij ) is a |V | × |E| matrix,
1, if edge ej is incident with vertex vi
bij =
0, otherwise
162 / 278
Notion of graphs
Degree of a vertex
I undirected graph:
I The degree of a vertex = the number of incident edges
I The handshaking theorem:
X
degree(v) = 2|E|
v∈V
163 / 278
Breadth-First Search (BFS)
I For searching a graph
I An archetype for many important graph algorithms
164 / 278
Review: queue and stack data structure
I Queues and stacks are dynamic sets in which the elements removed
from the set is prescribed.
I The queue implements a First-In-First-Out (FIFO) policy.
The stack implements a Last-In-First-Out (LIFO) policy.
I Queue supports the following operations:
I Enqueue(Q,v): insert element v into the queue Q
I Dequeue(Q): delete the head element from the queue Q
I Stack supports the following operations:
I Push(S,x): insert element x into the stack S
I Pop(S): delete the most recently inserted element the stack S
I There are several efficient ways to implement queues and stacks, take
O(1) time.
165 / 278
Breadth-First Search (BFS)
Example 1.
BFS(G,s)
for each vertex u in V-{s}
d[u] = +infty
endfor
d[s] = 0
Q = empty //create FIFO queue
Enqueue(Q, s)
while Q not empty
u = Dequeue(Q)
for each v in Adj[u]
if d[v] = +infty
d[v] = d[u] + 1
Enqueue(Q, v)
endif
endfor
endwhile
return d
166 / 278
Breadth-First Search (BFS)
Example 2.
BFS(G,s)
for each vertex u in V-{s}
d[u] = +infty
endfor
d[s] = 0
Q = empty //create FIFO queue
Enqueue(Q, s)
while Q not empty
u = Dequeue(Q)
for each v in Adj[u]
if d[v] = +infty
d[v] = d[u] + 1
Enqueue(Q, v)
endif
endfor
endwhile
return d
167 / 278
Breadth-First Search (BFS)
Example 3.
BFS(G,s)
for each vertex u in V-{s}
d[u] = +infty
endfor
d[s] = 0
Q = empty //create FIFO queue
Enqueue(Q, s)
while Q not empty
u = Dequeue(Q)
for each v in Adj[u]
if d[v] = +infty
d[v] = d[u] + 1
Enqueue(Q, v)
endif
endfor
endwhile
return d
168 / 278
Breadth-First Search (BFS)
I Breadth-first spanning tree
169 / 278
Depth-First Search (DFS)
I Another archetype for many important graph algorithms
I Input: G = (V, E)
Output: (1) two timestamps for every v ∈ V
d[v] = when v is first discovered.
f [v] = when v is finished.
(2) classification of edges
170 / 278
DFS
I Basic idea:
I go as deep as possible, then “back up”,
I edges are explored out of the most recently discovered vertex v that
still have unexplored edges leaving,
I when all of v’s edges have been explored, the search “backtracks” to
explore edges leaving the vertex from which v was discoverd.
171 / 278
DFS
DFS(G) // main routine : DFS-Visit(u) // subroutine
for each vertex u in V : color[u] = ‘‘gray’’
color[u] = ‘‘white’’ : time = time + 1; d[u] = time
endfor : for each v in Adj[u]
time = 0 : if color[v] = ‘‘white’’
for each vertex u in V : DFS-Visit(v)
if color[u] = ‘‘white’’ : endif
DFS-Visit(u) : end for
endif : color[u] = ‘‘black’’
endfor : time = time + 1; f[u] = time
Example 1.
172 / 278
DFS
DFS(G) // main routine : DFS-Visit(u) // subroutine
for each vertex u in V : color[u] = ‘‘gray’’
color[u] = ‘‘white’’ : time = time + 1; d[u] = time
endfor : for each v in Adj[u]
time = 0 : if color[v] = ‘‘white’’
for each vertex u in V : DFS-Visit(v)
if color[u] = ‘‘white’’ : endif
DFS-Visit(u) : end for
endif : color[u] = ‘‘black’’
endfor : time = time + 1; f[u] = time
Example 2.
173 / 278
DFS
DFS(G) // main routine : DFS-Visit(u) // subroutine
for each vertex u in V : color[u] = ‘‘gray’’
color[u] = ‘‘white’’ : time = time + 1; d[u] = time
endfor : for each v in Adj[u]
time = 0 : if color[v] = ‘‘white’’
for each vertex u in V : DFS-Visit(v)
if color[u] = ‘‘white’’ : endif
DFS-Visit(u) : end for
endif : color[u] = ‘‘black’’
endfor : time = time + 1; f[u] = time
Example 3.
174 / 278
DFS
Remarks:
I Vertices, from which exploration is incomplete, are proceessed in a
LIFO stack.
I Running time: Θ(|V | + |E|)
not big-O since guaranteed to examine every vertex and edge.
175 / 278
DFS
Classification of edges:
I T = Tree edge = encounter new vertex (gray to white)
176 / 278
DFS Classification of edges
DFS(G) // main routine : DFS-Visit(u) // subroutine T = Tree edge = encounter new vertex (gray to white)
for each vertex u in V : color[u] = ‘‘gray’’
color[u] = ‘‘white’’ : time = time + 1 B = Back edge = from descendant to ancestor (gray to gray)
endfor : d[u] = time F = Forward edge = from ancestor to descendant (gray to
time = 0 : for each v in Adj[u] black)
for each vertex u in V : if color[v] = ‘‘white’’
if color[u] = ‘‘white’’ : DFS-Visit(v) C = Cross edge = any other edges (between trees and
DFS-Visit(u) : end if subtrees) (gray to black)
endif : end for
endfor : color[u] = ‘‘black’’
// end of main routine : time = time + 1
: f[u] = time
: // end of subroutine
Example 1.
177 / 278
DFS Classification of edges
DFS(G) // main routine : DFS-Visit(u) // subroutine T = Tree edge = encounter new vertex (gray to white)
for each vertex u in V : color[u] = ‘‘gray’’
color[u] = ‘‘white’’ : time = time + 1 B = Back edge = from descendant to ancestor (gray to gray)
endfor : d[u] = time F = Forward edge = from ancestor to descendant (gray to
time = 0 : for each v in Adj[u] black)
for each vertex u in V : if color[v] = ‘‘white’’
if color[u] = ‘‘white’’ : DFS-Visit(v) C = Cross edge = any other edges (between trees and
DFS-Visit(u) : end if subtrees) (gray to black)
endif : end for
endfor : color[u] = ‘‘black’’
// end of main routine : time = time + 1
: f[u] = time
: // end of subroutine
Example 2.
178 / 278
DFS Classification of edges
DFS(G) // main routine : DFS-Visit(u) // subroutine T = Tree edge = encounter new vertex (gray to white)
for each vertex u in V : color[u] = ‘‘gray’’
color[u] = ‘‘white’’ : time = time + 1 B = Back edge = from descendant to ancestor (gray to gray)
endfor : d[u] = time F = Forward edge = from ancestor to descendant (gray to
time = 0 : for each v in Adj[u] black)
for each vertex u in V : if color[v] = ‘‘white’’
if color[u] = ‘‘white’’ : DFS-Visit(v) C = Cross edge = any other edges (between trees and
DFS-Visit(u) : end if subtrees) (gray to black)
endif : end for
endfor : color[u] = ‘‘black’’
// end of main routine : time = time + 1
: f[u] = time
: // end of subroutine
Example 3.
179 / 278
DFS vs. BFS
1. DFS: vertices from which the exploring is incomplete are processed in
a LIFO order (stack)
BFS: vertices to be explored are organized in a FIFO order (queue)
180 / 278
Applications of DFS
1. For a undirected graph,
(a) a DFS produces only Tree and Back edges
(b) Acyclic iff a DFS yeilds no Back edges
181 / 278
Topological sort
I A topological sort (TS) of a DAG G = (V, E) is a linear ordering of all
its vertices such that if (u, v) ∈ E, then u appears before v in the
ordering.
Example: given a DAG
TS (=linear ordering):
182 / 278
Topological sort
Applications: call-graph
183 / 278
Topological sort
Applications: call-graph of an integrated water flow model of California
Department of Water Resources
EXPLANATION
Redding
Element
Lake
Major River
Secondary River
Canal
Sacramento
San Francisco
Fresno
Bakersfield
184 / 278
Topological sort
I TS algorithm
185 / 278
Topological sort
Example: TS of “getting-dressed-graph”
22.4 Topological sort 613
1. DFS
22.4 Topological sort 613
jacket 3/4
jacket 3/4
(b) socks undershorts pants shoes watch shirt belt tie jacket
(b) socks
17/18
undershorts
11/16
pants
12/15
shoes
13/14
watch
9/10
shirt
1/8
belt
6/7
tie
2/5
jacket
3/4
17/18 11/16 12/15 13/14 9/10 1/8 6/7 2/5 3/4
Figure 22.7 (a) Professor Bumstead topologically sorts his clothing when getting dressed. Each
Figure
directed22.7 (a) /
edge .u; Professor Bumstead
means that garment topologically
u must be sorts
put on hisbefore
clothing when .
garment getting
The dressed.
discoveryEach
and
finishing times.u;
directed edge / ameans
from that garment
depth-first search areu must
shownbenext
put to
oneach
before garment
vertex. . The
(b) The samediscovery and
graph shown
finishing timessorted,
topologically from with
a depth-first search
its vertices are shown
arranged nexttotoright
from left eachinvertex.
order of(b) The samefinishing
decreasing graph shown
time.
topologically sorted,
All directed edges gowith
fromitsleft
vertices arranged from left to right in order of decreasing finishing time.
to right. 186 / 278
Topological sort
Theorem (correctness of the algorithm):
TS(G) produces a toplogical sort of a DAG G.
Proof: Just need to show that if (u, v) ∈ E, then f [v] < f [u] .
When we explore edge (u, v), u is gray, what’s the color of v?
I Is v gray too?
no, because then v would be ancestor of u, edge (u, v) is a back edge,
a contradiction of a DAG.
I Is v white?
yes, then v is descendant of u, by DFS, d[u] < d[v] < f [v] < f [u]
I Is v black?
yes, then v is already finished. Since we’re exploring (u, v), we have
not yet finished u, therefore f [v] < f [u]
187 / 278
Minimum Spanning Tree (MST)
I Undirected connected weighted graph G = (V, E, w)
I Weight function w : E −→ R
I Spanning tree: a tree that connects all vertices
Example
One of the most famous greedy algorithms, along with Huffman coding
189 / 278
MST
Two basic properties:
1. Optimal substructure: optimal tree contains optimal subtrees.
Let T be a MST of G = (V, E). Removing (u, v) of T partitions T
into two trees T1 and T2 . Then T1 is a MST of G1 = (V1 , E1 ) and T2
is a MST of G2 = (V2 , E2 ).5
6 Note: there is an abuse of notation here that we will view A as being both edges
and vertices.
191 / 278
MST
Prim’s algorithm
I Basic idea:
I starts from an arbitrary root r
I builds one tree, so that A is always a tree
I at each step, find the next lightest edge crossing cut (A, V − A) and
add this edge to A (“greedy choice”)
192 / 278
Review: Priority Queue
A priority queue maintains a set S of elements, each with an associated
value called a “key”, and supports the following operations:
I Search(S,k):
returns x in S with key[x] = k
I Insert(S, x)/Delete(S, x):
inserts/deletes the element x into the set S
I Maximum(S)/Minimum(S):
returns x in S with largest/smallest key
I Extract-max(S)/Extract-min(S):
removes and returns x in S with largest/smallest key
I Increase-key(S, x, k)/Decrease-key(S, x, k):
increases/decreases the value of element x’s key to the new value k
Recall that the priority queue has been used in Huffman coding.
193 / 278
MST
MST-Prim(G, w, r)
Q = empty
for each vertex u in V
key[u] = infty // min. weight of any edge (w,u) and w in A
pi[u] = nil // parent of u
Insert(Q, u)
endfor
Decrease-key(Q,r,0)
while Q not empty
u = Extract-Min(Q)
for each v in Adj[u]
if (v in Q) and (w(u,v) < key[v])
Decrease-key(Q, v, w(u,v))
pi[v] = u // parent of v
endif
endfor
endwhile
return A = { (v, pi[v]): v in V-{r} } // MST
194 / 278
MST Example 1. Run and illustrate
MST-Prim(G, w, r)
Q = empty
for each vertex u in V
key[u] = infty
pi[u] = nil
Insert(Q, u)
endfor
Decrease-key(Q,r,0)
while Q not empty
u = Extract-Min(Q)
for each v in Adj[u]
if (v in Q) and (w(u,v) < key[v])
Decrease-key(Q, v, w(u,v))
pi[v] = u // parent of v
endif
endfor
endwhile
return A = { (v, pi[v]): v in V-{r} }
195 / 278
MST Example 2. Run and illustrate
MST-Prim(G, w, r)
Q = empty
for each vertex u in V
key[u] = infty
pi[u] = nil
Insert(Q, u)
endfor
Decrease-key(Q,r,0)
while Q not empty
u = Extract-Min(Q)
for each v in Adj[u]
if (v in Q) and (w(u,v) < key[v])
Decrease-key(Q, v, w(u,v))
pi[v] = u // parent of v
endif
endfor
endwhile
return A = { (v, pi[v]): v in V-{r} }
196 / 278
MST
Running time of Prim’s algorithm
1. depends on how the priorty queue Q is implemented
2. Suppose Q is a binary heap (see Section 6.1)
I Initialize Q and the first for loop: O(|V | lg |V |)
I Decrease key of root r: O(lg |V |)
I While-loop:
a) |V | Extract-Min calls: O(|V | lg |V |)
b) ≤ |E| Decrease-Key calls: O(|E| lg |E|)
3. Total: O(|E| lg |V |)
4. Note: G is connected, lg |E| = Θ(lg |V |)
197 / 278
MST
Kruskal’s algorithm
I Basic idea:
I scan edges in increasing of weight
I put edge in the final MST T if no loop created
198 / 278
Review: Disjoint-Set
Disjoint-Set maintains a collection of S = {S1 , S2 , ...Sk } of disjoint
dynamic sets. Each set is identified by a representative, which is some
member of the set.
A disjoint-set data structure supports the following operations:
I Make-set(x):
creates a new set whose only member (and thus representative) is x.
I Union(x, y):
unites the sets that contain x and y, say Sx and Sy , into a new set
that is the union of these two sets: Sx ∪ Sy . The representative is any
member of Sx ∪ Sy .
I Find-set(x):
returns (a pointer to) the representative of the (unique) set containing
x.
199 / 278
MST
MST-Kruskal(G, w)
A = emtpy
for each vertex v in V
Make-set(v)
endfor
Sort the edges E in nondecreasing order by w
for each edge (u,v) in E, taken in nondecreasing order by w
if Find-set(u) \= Find-set(v)
A = A U {(u,v)}
Union(u,v)
endif
endfor
return A
200 / 278
MST Example 1. Run and illustrate
MST-Kruskal(G, w)
A = emtpy
for each vertex v in V
Make-set(v)
endfor
Sort the edges E in nondecreasing order by w
for each edge (u,v) in E, taken in nondecreasing order by w
if Find-set(u) \= Find-set(v)
A = A U {(u,v)}
Union(u,v)
endif
endfor
return A
201 / 278
MST
Running time of Kruskal’s algorithm
1. depends on the implementation of the disjoint-set
I |V | Make-Set ops
I 2|E| Find-Set ops
I |V | − 1 Union ops
2. Sort: Θ(|E| lg |E|)
3. Total: O(|E| lg |V |)
4. Note: G is connected, lg |E| = Θ(lg |V |)
202 / 278
Shortest paths – Intro
I Generalization of BFS to handle weighted graphs
I Weight function w : E −→ R
I Weight of path p = v0 → v1 → · · · → vk
k
X
w(p) = w(vi−1 , vi )
i=1
I Shortest-path weight u ; v
203 / 278
Shortest paths – Intro
I Shortest-path u ; v:
any path p such that w(p) = δ(u, v)
I Example:
204 / 278
Shortest paths – Intro
I Single-source shortest path problem (SSSP):
find shortest-paths from a given source vertex s ∈ V to every vertex
v∈V
I Basic SSSP algorithm: Bellman-Ford algorithm (discussed next)
I Variants:
I Single-destination: find shortest-path to a given destination vertex
(reverse the direction of each edge to become the single-source
problem)
I Single-pair: given u and v, find shortest-path from u to v
(no way know that’s better in worst case than solving single-source)
I All-pairs: find shortest-paths from u to v for all u, v ∈ V .
(By running Bellman-Ford once for each vertex, cost
O(V 2 E) = O(V 4 ) on dense graph. Can do better.
205 / 278
Shortest paths – Intro
Well-definedness
I Negative-weight edges are OK, as long as no negative-weight cycles
reachable from the source. Otherwise, can always get a shorter path
by going around the cycle again.
I The shortest path problem is ill-posed in graph with negative-weight
cycle
I Bellman-Ford algorithm can detect and report the existence of
negative-weight cycle
206 / 278
Shortest paths – Intro
I Optimal substructure property of SSSP:
subpaths of shortest-paths are shortest-paths.
207 / 278
Shortest paths – Intro
I Notation:
d[v]: shortest-path estimate
π[v]: predecessor of v
208 / 278
Shortest paths – Intro
Two key components of shortest-path algorithms:
I Initialization
for every vertex v in V
d[v] = infty
pi[v] = nil
endfor
d[s] = 0 // s = source vertex
I Relaxing an edge (u, v) : can we improve the shortest-path estimate
d[v] by going through u and taking the edge (u, v)?
if d[v] > d[u] + w(u,v)
d[v] = d[u] + w(u,v)
pi[v] = u
endif
209 / 278
Shortest paths – Intro
Basic properties:
1. Triangular inequality
for all (u, v) ∈ E, δ(u, v) ≤ δ(u, x) + δ(x, v)
2. Upper-bound property
Always have d[v] ≥ δ(s, v) for all v.
Once d[v] = δ(s, v), it never changes
3. No-path property
If δ(s, v) = ∞, then d[v] = ∞ always
4. Convergence property
If s ; u → v is a shortest-path, and d[u] = δ(s, u). Then after “Relax
u → v”, d[v] = δ(s, v)
210 / 278
Shortest paths – Algorithms
The Bellman-Ford algorithm
I Most basic algorithm for the shortest-path problem.
I Return
I TRUE if no negative-weight cycles reachable from source s
I FALSE otherwise.
211 / 278
Shortest paths – Algorithms
Bellman-Ford(G, w, s)
for each vertex v in V // initialization
d[v] = infty
pi[v] = nil
endfor
d[s] = 0
for i = 1 to |V|-1 // |V|-1 passes
for each edge (u,v) in E // in a prescribed order
if d[v] > d[u] + w(u,v) // relax if necessary
d[v] = d[u] + w(u,v)
pi[v] = u
endfor
endfor
for each edge (u,v) in E // final check pass
if d[v] > d[u] + w(u,v)
return FALSE
endfor
return TRUE, d, pi
212 / 278
Shortest paths – Algorithms
Bellman-Ford(G, w, s) Example 1: run and illustrate
for each vertex v in V
d[v] = infty
pi[v] = nil
endfor
d[s] = 0
for i = 1 to |V|-1
for each edge (u,v) in E
if d[v] > d[u] + w(u,v)
d[v] = d[u] + w(u,v)
pi[v] = u
endfor
endfor
for each edge (u,v) in E
if d[v] > d[u] + w(u,v)
return FALSE
endfor
return TRUE, d, pi
213 / 278
Shortest paths – Algorithms
Bellman-Ford(G, w, s) Example 2: run and illustrate
for each vertex v in V
d[v] = infty
pi[v] = nil
endfor
d[s] = 0
for i = 1 to |V|-1
for each edge (u,v) in E
if d[v] > d[u] + w(u,v)
d[v] = d[u] + w(u,v)
pi[v] = u
endfor
endfor
for each edge (u,v) in E
if d[v] > d[u] + w(u,v)
return FALSE
endfor
return TRUE, d, pi
214 / 278
Shortest paths – Algorithms
The Bellman-Ford algorithm
I Running time: Θ(|V | · |E|).
I Values you get on each pass and how quickly it converges depends on
order of relaxation (processing edges). But guaranteed to converge
after |V | − 1 passes, assuming no negative-weight cycles.
215 / 278
Shortest paths – Algorithms
Dijkstra’s algorithm
I No negative weight edges
216 / 278
Shortest paths – Algorithms
Dijkstra(G, w, s)
for each vertex v in V // Initialization
d[v] = infty
pi[v] = nil
endfor
d[s] = 0
Q = V // priority queue keyed by d[v]
while Q is not empty
u = Extract-Min(Q)
for all edge (u,v) in E
if d[v] > d[u] + w(u,v) // Relax if necessary
d[v] = d[u] + w(u,v)
pi[v] = u
endfor
endwhile
return d, pi
217 / 278
Shortest paths – Algorithms
Dijkstra(G, w, s) Example 1. run and illustrate
for each vertex v in V
d[v] = infty
pi[v] = nil
endfor
d[s] = 0
Q = V
while Q is not empty
u = Extract-Min(Q)
for all edge (u,v) in E
if d[v] > d[u] + w(u,v)
d[v] = d[u] + w(u,v)
pi[v] = u
endfor
endwhile
return d, pi
218 / 278
Shortest paths – Algorithms
Dijkstra(G, w, s) Example 2. run and illustrate
for each vertex v in V
d[v] = infty
pi[v] = nil
endfor
d[s] = 0
Q = V
while Q is not empty
u = Extract-Min(Q)
for all edge (u,v) in E
if d[v] > d[u] + w(u,v)
d[v] = d[u] + w(u,v)
pi[v] = u
endfor
endwhile
return d, pi
219 / 278
Shortest paths – Algorithms
Dijkstra’s algorithm
I Running time: O(|E| lg |V |) (binary heap)
220 / 278
Shortest paths – Algorithms
The SSSP in DAG
I DAG: can have negative-weight edges, but no negative-weight cycle.
221 / 278
Shortest paths – Algorithms
DAG-Shortest-Path(G, w, s)
Topological sort (TS) of vertices of G
for each vertex v in V
d[v] = infty
pi[v] = nil
endfor
d[s] = 0
for each vertex u taken in TS order
for each vertex v in Adj[u]
if d[v] > d[u] + w(u,v)
d[v] = d[u] + w(u,v)
pi[v] = u
endfor
endfor
return d, pi
222 / 278
Shortest paths – Algorithms
DAG-Shortest-Path(G, w, s) Example. run and illustrate
TS of G
for each vertex v in V
d[v] = infty
pi[v] = nil
endfor
d[s] = 0
for each vertex u in TS order
for each vertex v in Adj[u]
if d[v] > d[u] + w(u,v)
d[v] = d[u] + w(u,v)
pi[v] = u
endfor
endfor
return d, pi
223 / 278
Shortest-paths – Proofs
I Weight of path p = v0 → v1 → · · · → vk :
k
X
w(p) = w(vi−1 , vi )
i=1
I Shortest-path weight u ; v
p
min{w(p) : u ; v} if there exists a path u ; v
δ(u, v) =
∞ otherwise
I Shortest-path u ; v
any path p such that w(p) = δ(u, v)
224 / 278
Shortest-paths – Proofs
Triangular inequality:
for all (u, v) ∈ E, δ(u, v) ≤ δ(u, x) + δ(x, v).
225 / 278
Shortest-paths – Proofs
Upper-bound property:
1) Always have d[v] ≥ δ(s, v) for all v.
2) Once d[v] = δ(s, v), it never changes.
Proof. For item 1). Initially true since d[v] = ∞. By contradiction, suppose
there exists a vertex such that d[v] < δ(s, v). Without loss of generality, v
is first vertex for which this happens. Let u be the vertex that causes d[v]
change. Then d[v] = d[u] + w(u, v). So
which implies d[v] < d[u] + w(u, v). Contradicts d[v] = d[u] + w(u, v).
This completes the proof of item 1).
For item 2), once d[v] reaches δ(s, v), it never goes lower. It also never
goes up, since relaxations only lower shortest-path weights.
226 / 278
Shortest-paths – Proofs
No-path property:
If δ(s, v) = ∞, then d[v] = ∞ always.
Proof. The upper bound property d[v] ≥ δ(s, v) and δ(s, v) = ∞ imply
that d[v] = ∞.
227 / 278
Shortest-paths – Proofs
Convergence property:
If s ; u → v is a shortest-path, and d[u] = δ(s, u). Then after
“Relax u → v”, d[v] = δ(s, v).
Proof. After relaxation
On the other hand, by the upper bound property, we have d[v] ≥ δ(s, v).
Therefore, it must have d[v] = δ(s, v).
228 / 278
Shortest-paths – Proofs
Path relaxation property
Let p = v0 → v1 → · · · → vk be a shortest-path. If we relax in
order, (v0 , v1 ), (v1 , v2 ), . . . , (vk−1 , vk ), even intermixed with other
relaxations, then d[vk ] = δ(v0 , vk ).
Proof. We use the induction to show d[vi ] = δ(s, vi ) after (vi−1 , vi ) is
relaxed.
I Basis step: i = 0. Initially d[v0 ] = δ(s, v0 ) = δ(s, s)
I Inductive step: Assume d[vi−1 ] = δ(s, vi−1 ). Relax (vi−1 , vi ). By the
convergence property, d[vi ] = δ(s, vi ) afterward and d[vi ] never
changes.
229 / 278
Shortest-paths – Proofs
Correctness of the Bellman-Ford algorithm
It is guaranteed to converge after |V | − 1 passes, assuming no
negative-weight cycles.
Proof. Use the path-relaxation property.
Let v be reachable from s, and let p = v0 → v1 → · · · → vk be the shortest
path from s to v, where v0 = s and vk = v.
Since p is acyclic, the number of edges of p has ≤ |V | − 1 edges, so that
k ≤ |V | − 1.
Each iteration of the for loop realxes all edges:
I First iteration relaxes (v0 , v1 )
I Second iteration relaxes (v1 , v2 )
I ...
I kth iteration relaxes (vk−1 , vk )
By the path-relaxation property, d[v] = d[vk ] = δ(s, vk ) = δ(s, v).
230 / 278
Shortest-paths – Proofs
Correctness of Dijkstra’s algorithm
Show that d[u] = δ(s, u) when u is added to S in each iteration.
Proof:
I We prove by contradiction. Suppose there exists u such that
d[u] 6= δ(s, u). Without loss of generality, let u be the first vertex for
which d[u] 6= δ(s, u) when u is added to S in each iteration.
I Observation:
I u 6= s, since d[s] = δ(s, s) = 0.
I Therefore, s ∈ S and S 6= ∅
I There must have be some path s ; u, since otherwise
d[u] = δ(s, u) = ∞ by no-path property.
p
So, there is a path s ; u. Then there is a shortest path s ; u.
I Just before u is added to S, path p connects a vertex in S (i.e., s) to
a vertex in V − S (i.e., u). Let y be first vertex along p that’s in
V − S and and let x be y’s predecessor.
I Decompose p into
p1 p2
s;x→y;u
(could have x = s or y = u, so that p1 or p2 may have no edges.)
231 / 278
Shortest-paths – Proofs
Correctness of Dijkstra’s algorithm, cont’d
I Claim:7 d[y] = δ(s, y) when u is added to S.
I Now we can get a contradiction to d[u] 6= δ(s, u):
y is on shortest path s ; u, and all edge weights are nonnegative
⇓
δ(s, y) ≤ δ(s, u)
⇓
d[y] = δ(s, y) ≤ δ(s, u) ≤ d[u] (upper bound property)
Also, both y and u were in Q when we chose u, so that
d[u] ≤ d[y]
7 Proof. x ∈ S and u is the first vertex such that d[u] = δ(s, u) when u is added to S
233 / 278
NP-Completeness – overview
1. Introduction
2. P and NP
234 / 278
1. Introduction
(a) Tractable and intractable problems
I Problems that are solvable by polynomial-time algorithms are tractable
Almost all the algorithms we have studied thus far have been
polynomial-time algorithms on inputs of size n, their worst-case running
time is O(nk ) for some constant k.
235 / 278
1. Introduction
(b) NP-complete (NPC) problems: an informal definition
A large class of very diverse problems share the following properties:
1. We only know how to solve those problems in time much larger than
polynomial, namely exponential time.
236 / 278
1. Introduction
(c) Reasons to study NPC porblems – practical
I There is a large class of very diverse intractable problems, and the
difference between tractable and intractable may appear “only
slightly” – examples later;
I you can use a known algorithm for an intractable problem, and accept
that it will take a long long time to solve; or
I you can settle for approximating the solution, e.g., finding a nearly
best solution rather than the optimum; or
I you can change your problem formulation so that it is solvable in
polynomial time.
237 / 278
1. Introduction
(c) Reasons to study NPC porblems – theoretical
I We stated above that “We only know” how to solve those problems in
time much larger than polynomial, Not that we have proven that these
problems require exponential time.
I Indeed, this is one of the most famous problems in computer science:
?
P = NP
namely
238 / 278
1. Introduction
(d) P-vs-NP examples
Example 1.
I Shortest path:
finding the shortest path from a single source in a directed graph.
I Longest path:
finding the longest simple path between two vertices in a directed
graph.
239 / 278
1. Introduction
(d) P-vs-NP examples
Example 2.
I Euler tour:
given a connected, directed graph G, is there a cycle that visits each
edge exactly once (although it is allowed to visit each vertex more
than once)?
I Hamiltonian cycle:
given a connected directed graph G, is there a simple cycle that visits
each vertex exactly once?
The first one is solvable in polynomial time8 , and the second is NPC, but
the difference appears to be slight
241 / 278
1. Introduction
Traveling salesperson problem (TSP)
242 / 278
1. Introduction
(d) P-vs-NP examples
Example 4.
I Circuit value:
given a Boolean formula and its input, is the output True?
I Circuit satisfiability (SAT):
given a Boolean formula, is there a way to set the inputs so that the
output is True?
The first one is solvable in polynomial time, and the second is NPC, but
the difference appears to be slight.
243 / 278
1. Introduction
(e) Optimization problems and Decision problems
I Most of problems occur naturally as optimization problems,
I but they can also be formulated as decision problems, that is, problems
for which the output is a simple Yes or No answer for each input.
Remarks:
I To simplify discussion, we can consider only decision problems, rather
than optimization problems.
I The optimization problems are at least as hard to solve as the related
decision problems, we have not lost anything essential by doing so.
244 / 278
1. Introduction
(e) Optimization problems and Decision problems
Example 1
Graph coloring: A coloring of a graph G = (V, E) is a mapping
C:V →S
where S is a finite set of “colors”, such that
(u, v) ∈ E ⇒ C(u) 6= C(v)
I optimization problem: given G, determine the smallest number of
colors needed.
I decision problem: given G and a positive integer k, is there a coloring
of G using at most k colors?
245 / 278
1. Introduction
(e) Optimization problems and Decision problems
Example 2.
Hamiltonian cycle: A Hamiltonian cycle is cycle that passes through
every vertex exactly once.
246 / 278
1. Introduction
(e) Optimization problems and Decision problems
Example 3.
TSP (Traveling Salesperson Problem): given a weighted graph and
an integer k, is there a cycle that visits all vertices exactly once
(Hamiltonian cycle) whose total weight is k or less?
247 / 278
1. Introduction – recap
(a) Tractable and intractable problems
polynomial-boundness: O(nk )
(b) NP-complete problems – informal definition
(c) Reasons to study NPC problems
Practical and theoretical
(d) P and NP examples
difference may appear “only slightly”
(e) Optimization problems and decision problems
248 / 278
2. P and NP
(a) P: formal definition
I An algorithm is said to be polynomial bounded if its worst-case
complexity T (n) is bounded by a polynomial function of the
input size n:
T (n) = O(nk ).
249 / 278
2. P and NP
(b) NP: formal definition
I NP = the class of decision problems that are verifiable in polynomial
time.
i.e., if we were given a “certificate” (= a solution), then we could
verify that whether the certificate (the solution) is correct in
polynomial time.
I Examples:
I Circuit-SAT
I Hamiltonian cycle
I Graph coloring
250 / 278
2. P and NP
(c) P = NP ?
I P ⊆ NP
since if a problem is in P, then we can solve it in polynomial time
without even being given a certificate.
I Open problem:9
Does P ⊂ NP or P = NP ?
i.e., whether or not P is a proper subset of NP.
9 [Link]
251 / 278
2. P and NP
(d) P or NP
I The size of the input can change the classification of P or NP.
I Examples:
I Prime-testing problem:
n=10m
O(n) −→ O(10m )
I Knapsack problem
W =10m
O(nW ) −→ O(n · 10m )
253 / 278
3. NP-complete
(a) Introduction
I NP-complete (NPC) is the term used to describe decision problems
that are the hardest ones in NP in the following sense:
If there were a polynomial-bounded algorithm for an NPC problem,
then there would be a polynomial-bounded time for each problem
in NP.
254 / 278
3. NP-complete
(b) NPC: formal definition
I Decision problem A is NP-complete (NPC) if
(1) A ∈ NP and
(2) every other problems B in NP is polynomially reducible to A.
If a problem satisfies the property (2), but not necessarily the property (1),
we say the problem is NP-hard.11
11 Note: “NP-hard” does not mean “in NP and hard”. It means “at least as hard as
any problem in NP”. Thus a problem can be NP-hard and not be in NP.
255 / 278
3. NP-complete
(c) Polynomial reduction
I Let A and B be two decision problems, B is polynomially reducible to
A, if there is a poly-time computable transformation T such that
iff
Yes-instance of A ⇐⇒ Yes-instance of B
I Notation: B ≤T A
256 / 278
3. NP-complete
(c) Polynomial reduction
Example:
directed HC ≤T undirected HC
257 / 278
3. NP-complete
(c) Polynomial reduction
Example, cont’d:
v11 , v12 , v13 , v21 , v22 , v23 , . . . , vn1 , vn2 , vn3 , v11
is an undirected HC for G0 .
258 / 278
3. NP-complete
(c) Polynomial reduction
Example, cont’d:
6. “⇐”
I Suppose that G0 has an undirected HC, the three vertices v 1 , v 2 , v 3
that correspond to one vertex from G must be traversed consecutively
in the order v 1 , v 2 , v 3 or v 3 , v 2 , v 1 , since v 2 cannot be reached from
any other vertex in G0 .
I Since the other edges in G0 connect vertices with superscripts 1 or 3, if
for any one triple the order of the superscripts is 1-2-3, then the order
is 1-2-3 for all triples. Otherwise, it is 3-2-1 for all triples.
I Therefore, we may assume that the undirected HC of G0 is
vi11 , vi21 , vi31 , vi12 , vi22 , vi32 , . . . , vi1n , vi2n , vi3n , vi11 .
259 / 278
3. NP-complete
(d) Cook’s theorem and examples of known NPC problems
I Cook’s theorem (1971):12
Circuit-SAT is NPC.
I Known NPC problems:
I Graph coloring
I Hamiltonian cycle
I TSP
I Knapsack
I ... see next page for more.
NP
P
NPC
262 / 278
3. NP-complete – Recap
(a) Introduction
(b) NPC: formal definition
(c) Polynomial reduction
(d) Cook’s theorem and examples of known NPC problems
(e) P, NP and NPC
263 / 278
4. How to prove a problem is NPC
I The reducibility relation “≤T ” is transitive, i.e,
A ≤T B and B ≤T C imply A ≤T C
264 / 278
4. How to prove a problem is NPC
I Why sufficient? the logic is as follows:
Since B is NPC, all problems in NP is reducible to B.
Show B is reducible to A.
Then all problems in NP is reducible to A.
Therefore, A is NPC
265 / 278
4. How to prove a problem is NPC
Example 1.
The directed HC is known to be NPC. Use this fact to prove that
Undirected HC is NPC.
Proof:
(1) By direct verification, we know that undirected HC is in NP.
(2)
Step A: Define a transformation T
Step B: Show that
directed HC ≤T undirected HC
266 / 278
4. How to prove a problem is NP-complete
Example 1, cont’d:
We now show that
directed HC ≤T undirected HC
Step A
I Define transformation T :
Let G = (V, E) be a directed graph. Define G to the
undirected graph G0 = (V 0 , E 0 ) by the following
transformation T :
I v∈V −→ v 1 , v 2 , v 3 ∈ V 0 and (v 1 , v 2 ), (v 2 , v 3 ) ∈ E 0
I (u, v) ∈ E −→ (u3 , v 1 ) ∈ E 0
I T is polynomial-time computable.
267 / 278
4. How to prove a problem is NP-complete
Example 1, cont’d:
268 / 278
4. How to prove a problem is NPC
Example 1, cont’d
Step B: We show that
G has a HC ⇐⇒ G0 has a HC.
“⇒” Suppose that G has a directed HC: v1 , v2 , . . . , vn , v1 Then
v11 , v12 , v13 , v21 , v22 , v23 , . . . , vn1 , vn2 , vn3 , v11
is an undirected HC for G0 .
269 / 278
4. How to prove a problem is NPC
Example 1, cont’d
Step B: We show that
G has a HC ⇐⇒ G0 has a HC.
“⇒” Suppose that G has a directed HC: v1 , v2 , . . . , vn , v1 Then
v11 , v12 , v13 , v21 , v22 , v23 , . . . , vn1 , vn2 , vn3 , v11
is an undirected HC for G0 .
“⇐” 1. Suppose that G0 has an undirected HC, the three vertices v 1 , v 2 , v 3
that correspond to one vertex from G must be traversed consecutively
in the order v 1 , v 2 , v 3 or v 3 , v 2 , v 1 , since v 2 cannot be reached from
any other vertex in G0 .
2. Since the other edges in G0 connect vertices with superscripts 1 or 3, if
for any one triple the order of the superscripts is 1, 2, 3, then the order
is 1, 2, 3 for all triples. Otherwise, it is 3, 2, 1 for all triples.
3. Therefore, we may assume that the undirected HC of G0 is
vi11 , vi21 , vi31 , vi12 , vi22 , vi32 , . . . , vi1n , vi2n , vi3n , vi11 .
270 / 278
4. How to prove a problem is NPC
Example 2, cont’d
X
I Let S be an instance of Subset-Sum with w = si and the target c.
si ∈S
I Define the set S 0 (i.e., the transformation T from S to S 0 ) as follows:
271 / 278
4. How to prove a problem is NPC
Example 2, cont’d
=⇒ Let J ⊆ S and the elements in J sum to c. Then J ∪ {u} sum to 2w.
Note that the elements in J = S − J sum to w − c. Hence, J ∪ {v} also
sums to 2w. Therefore, S 0 can be partioned into J ∪ {u} and J ∪ {v}
where both partitions sum to 2w. Thus, Yes of Subset-Sum transforms to a
Yes of Set-Partition.
272 / 278
4. How to prove a problem is NPC
Example 2, cont’d
⇐= Assume S 0 can be partitioned into two sets, T and T = S 0 − T , such
that X X
x= x. (4)
x∈T x∈T
Since w + u + v = 4w, the sum of the elements in both sets must be equal
to 2w. Therefore, u must be in one set and v must be in the other because
u + v = 3w. Without loss of generality, let u ∈ T . Then
X X X
2w = x=u+ x = 2w − c + x.
x∈T x∈T −u x∈T −u
It implies that X
x=c
x∈T −u
273 / 278
5. How to solve a NPC problem
Example 1: Bin Packing problem
Suppose we have an unlimited number of bins, each of capacity 1,
and n objects with sizes s1 , s2 , . . . , sn , where 0 < si ≤ 1.
I Optimization problem: Determine the smallest number of bins into
which objects can be packed and find an optimal packing.
I Decision problem: Do the objects fit in k bins?
274 / 278
5. How to solve a NP-complete problem
Approximate algorithm for the Bin Packing
I First-fit strategy (greedy):
places an object in the first bin into which it fits.
I Example: Objects = {0.8, 0.5, 0.4, 0.4, 0.3, 0.2, 0.2, 0.2}
I First-fit strategy solution:
B1 B2 B3 B4
0.2
0.2 0.4 0.3
0.8 0.5 0.4 0.2
I Optimal packing:
B1 B2 B3
0.2 0.2
0.2 0.3 0.4
0.8 0.5 0.4
275 / 278
5. How to solve a NP-complete problem
n
X
Theorem. Let S = si .
i=1
1. The optimal number of bins required is at least dSe
2. The number of bins used by the first-fit strategy is never more than
d2Se.
276 / 278
5. How to solve a NP-complete problem
The vertex-cover problem:
I A vertex-cover of an undirected graph G = (V, E) is a subset set of
V 0 ⊆ V such that if (u, v) ∈ E, then u ∈ V 0 (inclusive) or v ∈ V 0 .
I In other words, each vertex “covers” its incident edges, and a vertex
cover for G is a set of vertices that covers all edges in E.
I The size of a vertex cover is the number of vertices in it.
I Decision problem: determine whether a graph has a vertex cover of a
given size k
I Optimization problem: find a vertex cover of minimum size.
I Theorem. The vertex-cover problem is NPC.
277 / 278
5. How to solve a NP-complete problem
The vertex-cover problem:
I An approximate algorithm
C=∅
E0 = E
while E 0 6= ∅
let (u, v) be an arbitrary edge of E 0
C = C ∪ {u, v}
remove from E 0 every edge incident on either u or v.
endwhile
return C
I Theorem. The size of the vertex-cover is no more than twice the size
of an optimal vertex cover.
278 / 278