(BQ) Part 1 book Introduction to algorithms has contents Data structures for disjoint sets, elementary graph algorithms, minimum spanning trees, single source shortest paths, maximum flow, multithreaded algorithms, matrix operations,...and other contents.
Trang 1Some applications involve grouping n distinct elements into a collection of disjointsets These applications often need to perform two operations in particular: findingthe unique set that contains a given element and uniting two sets This chapterexplores methods for maintaining a data structure that supports these operations.Section 21.1 describes the operations supported by a disjoint-set data structureand presents a simple application In Section 21.2, we look at a simple linked-listimplementation for disjoint sets Section 21.3 presents a more efficient represen-tation using rooted trees The running time using the tree representation is theo-retically superlinear, but for all practical purposes it is linear Section 21.4 definesand discusses a very quickly growing function and its very slowly growing inverse,which appears in the running time of operations on the tree-based implementation,and then, by a complex amortized analysis, proves an upper bound on the runningtime that is just barely superlinear.
21.1 Disjoint-set operations
A disjoint-set data structure maintains a collectionS D fS1; S2; : : : ; Skg of
dis-joint dynamic sets We identify each set by a representative, which is some
mem-ber of the set In some applications, it doesn’t matter which memmem-ber is used as therepresentative; we care only that if we ask for the representative of a dynamic settwice without modifying the set between the requests, we get the same answer bothtimes Other applications may require a prespecified rule for choosing the repre-sentative, such as choosing the smallest member in the set (assuming, of course,that the elements can be ordered)
As in the other dynamic-set implementations we have studied, we represent eachelement of a set by an object Letting x denote an object, we wish to support thefollowing operations:
Trang 2MAKE-SET.x/ creates a new set whose only member (and thus representative)
is x Since the sets are disjoint, we require that x not already be in some otherset
UNION.x; y/ unites the dynamic sets that contain x and y, say Sx and Sy, into anew set that is the union of these two sets We assume that the two sets are dis-joint prior to the operation The representative of the resulting set is any member
of Sx [ Sy, although many implementations of UNIONspecifically choose therepresentative of either Sx or Sy as the new representative Since we requirethe sets in the collection to be disjoint, conceptually we destroy sets Sx and Sy,removing them from the collectionS In practice, we often absorb the elements
of one of the sets into the other set
FIND-SET.x/ returns a pointer to the representative of the (unique) set ing x
contain-Throughout this chapter, we shall analyze the running times of disjoint-set datastructures in terms of two parameters: n, the number of MAKE-SET operations,and m, the total number of MAKE-SET, UNION, and FIND-SEToperations Sincethe sets are disjoint, each UNION operation reduces the number of sets by one.After n 1 UNION operations, therefore, only one set remains The number ofUNION operations is thus at most n 1 Note also that since the MAKE-SEToperations are included in the total number of operations m, we have m n Weassume that the n MAKE-SEToperations are the first n operations performed
An application of disjoint-set data structures
One of the many applications of disjoint-set data structures arises in ing the connected components of an undirected graph (see Section B.4) Fig-ure 21.1(a), for example, shows a graph with four connected components
determin-The procedure CONNECTED-COMPONENTS that follows uses the disjoint-setoperations to compute the connected components of a graph Once CONNECTED-COMPONENTS has preprocessed the graph, the procedure SAME-COMPONENTanswers queries about whether two vertices are in the same connected component.1
(In pseudocode, we denote the set of vertices of a graph G by G: V and the set of edges by G: E.)
1 When the edges of the graph are static—not changing over time—we can compute the connected components faster by using depth-first search (Exercise 22.3-12) Sometimes, however, the edges are added dynamically and we need to maintain the connected components as each edge is added In this case, the implementation given here can be more efficient than running a new depth-first search for each new edge.
Trang 3Figure 21.1 (a) A graph with four connected components: fa; b; c; d g, fe; f; gg, fh; ig, and fj g.
(b) The collection of disjoint sets after processing each edge.
3 else returnFALSE
The procedure CONNECTED-COMPONENTS initially places each vertex in itsown set Then, for each edge u; /, it unites the sets containing u and ByExercise 21.1-2, after processing all the edges, two vertices are in the same con-nected component if and only if the corresponding objects are in the same set.Thus, CONNECTED-COMPONENTS computes sets in such a way that the proce-dure SAME-COMPONENTcan determine whether two vertices are in the same con-
Trang 4nected component Figure 21.1(b) illustrates how CONNECTED-COMPONENTScomputes the disjoint sets.
In an actual implementation of this connected-components algorithm, the sentations of the graph and the disjoint-set data structure would need to referenceeach other That is, an object representing a vertex would contain a pointer tothe corresponding disjoint-set object, and vice versa These programming detailsdepend on the implementation language, and we do not address them further here
repre-Exercises
21.1-1
Suppose that CONNECTED-COMPONENTS is run on the undirected graph G D.V; E/, where V D fa; b; c; d; e; f; g; h; i; j; kg and the edges of E are pro-cessed in the order d; i /; f; k/; g; i /; b; g/; a; h/; i; j /; d; k/; b; j /; d; f /;.g; j /; a; e/ List the vertices in each connected component after each iteration oflines 3–5
21.2 Linked-list representation of disjoint sets
Figure 21.2(a) shows a simple way to implement a disjoint-set data structure: each
set is represented by its own linked list The object for each set has attributes head, pointing to the first object in the list, and tail, pointing to the last object Each
object in the list contains a set member, a pointer to the next object in the list, and
a pointer back to the set object Within each linked list, the objects may appear inany order The representative is the set member in the first object in the list.With this linked-list representation, both MAKE-SET and FIND-SET are easy,requiring O.1/ time To carry out MAKE-SET.x/, we create a new linked listwhose only object is x For FIND-SET.x/, we just follow the pointer from x back
to its set object and then return the member in the object that head points to For
example, in Figure 21.2(a), the call FIND-SET.g/ would return f
Trang 5object Each set object has pointers head and tail to the first and last objects, respectively (b) The
result of U NION g; e/, which appends the linked list containing e to the linked list containing g The representative of the resulting set is f The set object for e’s list, S2, is destroyed.
A simple implementation of union
The simplest implementation of the UNIONoperation using the linked-list set resentation takes significantly more time than MAKE-SETor FIND-SET As Fig-ure 21.2(b) shows, we perform UNION.x; y/ by appending y’s list onto the end
rep-of x’s list The representative rep-of x’s list becomes the representative rep-of the resulting
set We use the tail pointer for x’s list to quickly find where to append y’s list
Be-cause all members of y’s list join x’s list, we can destroy the set object for y’s list.Unfortunately, we must update the pointer to the set object for each object origi-nally on y’s list, which takes time linear in the length of y’s list In Figure 21.2, forexample, the operation UNION.g; e/ causes pointers to be updated in the objectsfor b, c, e, and h
In fact, we can easily construct a sequence of m operations on n objects thatrequires ‚.n2/ time Suppose that we have objects x1; x2; : : : ; xn We executethe sequence of n MAKE-SET operations followed by n 1 UNION operationsshown in Figure 21.3, so that m D 2n 1 We spend ‚.n/ time performing the nMAKE-SET operations Because the i th UNION operation updates i objects, thetotal number of objects updated by all n 1 UNIONoperations is
Trang 6Operation Number of objects updated
The total number of operations is 2n 1, and so each operation on average requires
‚.n/ time That is, the amortized time of an operation is ‚.n/
longer, breaking ties arbitrarily With this simple weighted-union heuristic, a
sin-gle UNIONoperation can still take .n/ time if both sets have .n/ members Asthe following theorem shows, however, a sequence of m MAKE-SET, UNION, andFIND-SEToperations, n of which are MAKE-SEToperations, takes O.m C n lg n/time
Theorem 21.1
Using the linked-list representation of disjoint sets and the weighted-union tic, a sequence of m MAKE-SET, UNION, and FIND-SET operations, n of whichare MAKE-SEToperations, takes O.m C n lg n/ time
Trang 7heuris-Proof Because each UNION operation unites two disjoint sets, we perform atmost n 1 UNIONoperations over all We now bound the total time taken by theseUNIONoperations We start by determining, for each object, an upper bound on thenumber of times the object’s pointer back to its set object is updated Consider aparticular object x We know that each time x’s pointer was updated, x must havestarted in the smaller set The first time x’s pointer was updated, therefore, theresulting set must have had at least 2 members Similarly, the next time x’s pointerwas updated, the resulting set must have had at least 4 members Continuing on,
we observe that for any k n, after x’s pointer has been updateddlg ke times,the resulting set must have at least k members Since the largest set has at most nmembers, each object’s pointer is updated at mostdlg ne times over all the UNIONoperations Thus the total time spent updating object pointers over all UNION
operations is O.n lg n/ We must also account for updating the tail pointers and
the list lengths, which take only ‚.1/ time per UNIONoperation The total timespent in all UNIONoperations is thus O.n lg n/
The time for the entire sequence of m operations follows easily Each MSETand FIND-SET operation takes O.1/ time, and there are O.m/ of them Thetotal time for the entire sequence is thus O.m C n lg n/
AKE-Exercises
21.2-1
Write pseudocode for MAKE-SET, FIND-SET, and UNION using the linked-listrepresentation and the weighted-union heuristic Make sure to specify the attributesthat you assume for set objects and list objects
21.2-2
Show the data structure that results and the answers returned by the FIND-SEToperations in the following program Use the linked-list representation with theweighted-union heuristic
Trang 8Assume that if the sets containing xiand xj have the same size, then the operationUNION.xi; xj/ appends xj’s list onto xi’s list.
21.2-3
Adapt the aggregate proof of Theorem 21.1 to obtain amortized time bounds
of O.1/ for MAKE-SETand FIND-SETand O.lg n/ for UNIONusing the list representation and the weighted-union heuristic
linked-21.2-4
Give a tight asymptotic bound on the running time of the sequence of operations inFigure 21.3 assuming the linked-list representation and the weighted-union heuris-tic
21.2-5
Professor Gompers suspects that it might be possible to keep just one pointer in
each set object, rather than two (head and tail), while keeping the number of
point-ers in each list element at two Show that the professor’s suspicion is well founded
by describing how to represent each set by a linked list such that each operationhas the same running time as the operations described in this section Describealso how the operations work Your scheme should allow for the weighted-union
heuristic, with the same effect as described in this section (Hint: Use the tail of a
linked list as its set’s representative.)
21.2-6
Suggest a simple change to the UNIONprocedure for the linked-list representation
that removes the need to keep the tail pointer to the last object in each list Whether
or not the weighted-union heuristic is used, your change should not change theasymptotic running time of the UNION procedure (Hint: Rather than appending
one list to another, splice them together.)
21.3 Disjoint-set forests
In a faster implementation of disjoint sets, we represent sets by rooted trees, with
each node containing one member and each tree representing one set In a
disjoint-set forest, illustrated in Figure 21.4(a), each member points only to its parent The
root of each tree contains the representative and is its own parent As we shallsee, although the straightforward algorithms that use this representation are nofaster than ones that use the linked-list representation, by introducing two heuris-tics—“union by rank” and “path compression”—we can achieve an asymptoticallyoptimal disjoint-set data structure
Trang 9Figure 21.4 A disjoint-set forest (a) Two trees representing the two sets of Figure 21.2 The
tree on the left represents the set fb; c; e; hg, with c as the representative, and the tree on the right represents the setfd; f; gg, with f as the representative (b) The result of UNION e; g/.
We perform the three disjoint-set operations as follows A MAKE-SEToperationsimply creates a tree with just one node We perform a FIND-SET operation byfollowing parent pointers until we find the root of the tree The nodes visited on
this simple path toward the root constitute the find path A UNION operation,shown in Figure 21.4(b), causes the root of one tree to point to the root of the other
Heuristics to improve the running time
So far, we have not improved on the linked-list implementation A sequence of
n 1 UNIONoperations may create a tree that is just a linear chain of n nodes Byusing two heuristics, however, we can achieve a running time that is almost linear
in the total number of operations m
The first heuristic, union by rank, is similar to the weighted-union heuristic we
used with the linked-list representation The obvious approach would be to makethe root of the tree with fewer nodes point to the root of the tree with more nodes.Rather than explicitly keeping track of the size of the subtree rooted at each node,
we shall use an approach that eases the analysis For each node, we maintain a
rank, which is an upper bound on the height of the node In union by rank, we
make the root with smaller rank point to the root with larger rank during a UNIONoperation
The second heuristic, path compression, is also quite simple and highly
effec-tive As shown in Figure 21.5, we use it during FIND-SEToperations to make eachnode on the find path point directly to the root Path compression does not changeany ranks
Trang 10b
c d
Figure 21.5 Path compression during the operation F IND -S ET Arrows and self-loops at roots are
omitted (a) A tree representing a set prior to executing FIND -S ET a/ Triangles represent subtrees
whose roots are the nodes shown Each node has a pointer to its parent (b) The same set after
executing F IND -S ET a/ Each node on the find path now points directly to the root.
Pseudocode for disjoint-set forests
To implement a disjoint-set forest with the union-by-rank heuristic, we must keep
track of ranks With each node x, we maintain the integer value x: rank, which is
an upper bound on the height of x (the number of edges in the longest simple pathbetween x and a descendant leaf) When MAKE-SET creates a singleton set, thesingle node in the corresponding tree has an initial rank of 0 Each FIND-SEToper-ation leaves all ranks unchanged The UNIONoperation has two cases, depending
on whether the roots of the trees have equal rank If the roots have unequal rank,
we make the root with higher rank the parent of the root with lower rank, but theranks themselves remain unchanged If, instead, the roots have equal ranks, wearbitrarily choose one of the roots as the parent and increment its rank
Let us put this method into pseudocode We designate the parent of node x
by x: p The LINKprocedure, a subroutine called by UNION, takes pointers to tworoots as inputs
Trang 11The FIND-SETprocedure is a two-pass method: as it recurses, it makes one pass
up the find path to find the root, and as the recursion unwinds, it makes a secondpass back down the find path to update each node to point directly to the root Eachcall of FIND-SET.x/ returns x:p in line 3 If x is the root, then FIND-SETskips
line 2 and instead returns x: p, which is x; this is the case in which the recursion bottoms out Otherwise, line 2 executes, and the recursive call with parameter x: p
returns a pointer to the root Line 2 updates node x to point directly to the root,and line 3 returns this pointer
Effect of the heuristics on the running time
Separately, either union by rank or path compression improves the running time ofthe operations on disjoint-set forests, and the improvement is even greater when
we use the two heuristics together Alone, union by rank yields a running time
of O.m lg n/ (see Exercise 21.4-4), and this bound is tight (see Exercise 21.3-3).Although we shall not prove it here, for a sequence of n MAKE-SET opera-tions (and hence at most n 1 UNION operations) and f FIND-SET opera-tions, the path-compression heuristic alone gives a worst-case running time of
‚.n C f 1 C log2Cf =nn//
Trang 12When we use both union by rank and path compression, the worst-case running
time is O.m ˛.n//, where ˛.n/ is a very slowly growing function, which we
de-fine in Section 21.4 In any conceivable application of a disjoint-set data structure,
˛.n/ 4; thus, we can view the running time as linear in m in all practical tions Strictly speaking, however, it is superlinear In Section 21.4, we prove thisupper bound
Trang 13? 21.4 Analysis of union by rank with path compression
As noted in Section 21.3, the combined union-by-rank and path-compression ristic runs in time O.m ˛.n// for m disjoint-set operations on n elements In thissection, we shall examine the function ˛ to see just how slowly it grows Then weprove this running time using the potential method of amortized analysis
heu-A very quickly growing function and its very slowly growing inverse
For integers k 0 and j 1, we define the function Ak.j / as
Ak.j / D
(
A.j C1/k1 j / if k 1 ;where the expression A.j C1/k1 j / uses the functional-iteration notation given in Sec-tion 3.2 Specifically, A.0/k1.j / D j and A.i /k1.j / D Ak1.A.i 1/k1 j // for i 1
We will refer to the parameter k as the level of the function A.
The function Ak.j / strictly increases with both j and k To see just how quicklythis function grows, we first obtain closed-form expressions for A1.j / and A2.j /
Lemma 21.2
For any integer j 1, we have A1.j / D 2j C 1
Proof We first use induction on i to show that A.i /0 j / D j Ci For the base case,
we have A.0/0 j / D j D j C 0 For the inductive step, assume that A.i 1/0 j / D
j C i 1/ Then A.i /0 j / D A0.A.i 1/0 j // D j C i 1// C 1 D j C i Finally,
we note that A1.j / D A.j C1/0 j / D j C j C 1/ D 2j C 1
Lemma 21.3
For any integer j 1, we have A2.j / D 2j C1.j C 1/ 1
Proof We first use induction on i to show that A.i /1 j / D 2i.j C 1/ 1 Forthe base case, we have A.0/1 j / D j D 20.j C 1/ 1 For the inductive step,assume that A.i 1/1 j / D 2i 1.j C 1/ 1 Then A.i /1 j / D A1.A.i 1/1 j // D
A1.2i 1.j C 1/ 1/ D 2.2i 1.j C1/1/C1 D 2i.j C1/2C1 D 2i.j C1/1.Finally, we note that A2.j / D A.j C1/1 j / D 2j C1.j C 1/ 1
Now we can see how quickly Ak.j / grows by simply examining Ak.1/ for levels
k D 0; 1; 2; 3; 4 From the definition of A0.k/ and the above lemmas, we have
A 1/ D 1 C 1 D 2, A 1/ D 2 1 C 1 D 3, and A 1/ D 21C1 1 C 1/ 1 D 7
Trang 14“” denotes the “much-greater-than” relation.)
We define the inverse of the function Ak.n/, for integer n 0, by
Trang 15Properties of ranks
In the remainder of this section, we prove an O.m ˛.n// bound on the running time
of the disjoint-set operations with union by rank and path compression In order toprove this bound, we first prove some simple properties of ranks
Lemma 21.4
For all nodes x, we have x: rank x: p: rank, with strict inequality if x ¤ x: p The value of x: rank is initially 0 and increases through time until x ¤ x: p; from then on, x: rank does not change The value of x: p: rank monotonically increases
over time
Proof The proof is a straightforward induction on the number of operations, ing the implementations of MAKE-SET, UNION, and FIND-SET that appear inSection 21.3 We leave it as Exercise 21.4-1
us-Corollary 21.5
As we follow the simple path from any node toward a root, the node ranks strictlyincrease
Lemma 21.6
Every node has rank at most n 1
Proof Each node’s rank starts at 0, and it increases only upon LINKoperations.Because there are at most n 1 UNION operations, there are also at most n 1LINK operations Because each LINK operation either leaves all ranks alone orincreases some node’s rank by 1, all ranks are at most n 1
Lemma 21.6 provides a weak bound on ranks In fact, every node has rank atmostblg nc (see Exercise 21.4-2) The looser bound of Lemma 21.6 will sufficefor our purposes, however
Proving the time bound
We shall use the potential method of amortized analysis (see Section 17.3) to provethe O.m ˛.n// time bound In performing the amortized analysis, we will find itconvenient to assume that we invoke the LINK operation rather than the UNIONoperation That is, since the parameters of the LINKprocedure are pointers to tworoots, we act as though we perform the appropriate FIND-SET operations sepa-rately The following lemma shows that even if we count the extra FIND-SETop-erations induced by UNIONcalls, the asymptotic running time remains unchanged
Trang 16Lemma 21.7
Suppose we convert a sequence S0of m0 MAKE-SET, UNION, and FIND-SETerations into a sequence S of m MAKE-SET, LINK, and FIND-SEToperations byturning each UNIONinto two FIND-SEToperations followed by a LINK Then, ifsequence S runs in O.m ˛.n// time, sequence S0 runs in O.m0˛.n// time
op-Proof Since each UNIONoperation in sequence S0is converted into three tions in S , we have m0 m 3m0 Since m D O.m0/, an O.m ˛.n// time boundfor the converted sequence S implies an O.m0˛.n// time bound for the originalsequence S0
opera-In the remainder of this section, we shall assume that the initial sequence of m0MAKE-SET, UNION, and FIND-SET operations has been converted to a sequence
of m MAKE-SET, LINK, and FIND-SEToperations We now prove an O.m ˛.n//time bound for the converted sequence and appeal to Lemma 21.7 to prove theO.m0˛.n// running time of the original sequence of m0operations
Potential function
The potential function we use assigns a potential q.x/ to each node x in thedisjoint-set forest after q operations We sum the node potentials for the poten-tial of the entire forest: ˆq D P
xq.x/, where ˆq denotes the potential of theforest after q operations The forest is empty prior to the first operation, and wearbitrarily set ˆ0 D 0 No potential ˆq will ever be negative
The value of q.x/ depends on whether x is a tree root after the qth operation
If it is, or if x: rank D 0, then q.x/ D ˛.n/ x:rank.
Now suppose that after the qth operation, x is not a root and that x: rank 1.
We need to define two auxiliary functions on x before we can define q.x/ First
we define
level.x/ D maxfk W x:p:rank Ak.x:rank/g :
That is, level.x/ is the greatest level k for which Ak, applied to x’s rank, is nogreater than x’s parent’s rank
We claim that
which we see as follows We have
x:p:rank x:rank C 1 (by Lemma 21.4)
D A0.x:rank/ (by definition of A0.j /) ,which implies that level.x/ 0, and we have
Trang 17A˛.n/.x:rank/ A˛.n/.1/ (because Ak.j / is strictly increasing)
> x:p:rank (by Lemma 21.6) , which implies that level.x/ < ˛.n/ Note that because x: p: rank monotonically
increases over time, so does level.x/
The second auxiliary function applies when x: rank 1:
iter.x/ D max˚
i W x:p:rank A.i /level.x/.x:rank/ :That is, iter.x/ is the largest number of times we can iteratively apply Alevel.x/,applied initially to x’s rank, before we get a value greater than x’s parent’s rank
We claim that when x: rank 1, we have
which we see as follows We have
x:p:rank Alevel.x/.x:rank/ (by definition of level.x/)
D A.1/level.x/.x:rank/ (by definition of functional iteration) ,
which implies that iter.x/ 1, and we have
A.x: rankC1/level.x/ .x:rank/ D Alevel.x/C1.x:rank/ (by definition of Ak.j /)
> x:p:rank (by definition of level.x/) ,
which implies that iter.x/ x: rank Note that because x: p: rank monotonically
increases over time, in order for iter.x/ to decrease, level.x/ must increase As long
as level.x/ remains unchanged, iter.x/ must either increase or remain unchanged.With these auxiliary functions in place, we are ready to define the potential ofnode x after q operations:
q.x/ D
(
.˛.n/ level.x//x:rank iter.x/ if x is not a root and x:rank 1 :
We next investigate some useful properties of node potentials
Lemma 21.8
For every node x, and for all operation counts q, we have
0 q.x/ ˛.n/ x:rank :
Trang 18Proof If x is a root or x: rank D 0, then q.x/ D ˛.n/x:rank by definition Now suppose that x is not a root and that x: rank 1 We obtain a lower bound on q.x/
by maximizing level.x/ and iter.x/ By the bound (21.1), level.x/ ˛.n/ 1, and
by the bound (21.2), iter.x/ x: rank Thus,
q.x/ D ˛.n/ level.x// x:rank iter.x/
.˛.n/ ˛.n/ 1// x:rank x:rank
D x:rank x:rank
D 0 :Similarly, we obtain an upper bound on q.x/ by minimizing level.x/ and iter.x/
By the bound (21.1), level.x/ 0, and by the bound (21.2), iter.x/ 1 Thus,
q.x/ .˛.n/ 0/ x:rank 1
D ˛.n/ x:rank 1
< ˛.n/ x:rank :
Corollary 21.9
If node x is not a root and x: rank > 0, then q.x/ < ˛.n/ x:rank.
Potential changes and amortized costs of operations
We are now ready to examine how the disjoint-set operations affect node potentials.With an understanding of the change in potential due to each operation, we candetermine each operation’s amortized cost
Lemma 21.10
Let x be a node that is not a root, and suppose that the qth operation is either aLINKor FIND-SET Then after the qth operation, q.x/ q1.x/ Moreover, if
x:rank 1 and either level.x/ or iter.x/ changes due to the qth operation, then
q.x/ q1.x/ 1 That is, x’s potential cannot increase, and if it has positiverank and either level.x/ or iter.x/ changes, then x’s potential drops by at least 1
Proof Because x is not a root, the qth operation does not change x: rank, and
because n does not change after the initial n MAKE-SEToperations, ˛.n/ remainsunchanged as well Hence, these components of the formula for x’s potential re-
main the same after the qth operation If x: rank D 0, then q.x/ D q1.x/ D 0
Now assume that x: rank 1.
Recall that level.x/ monotonically increases over time If the qth operationleaves level.x/ unchanged, then iter.x/ either increases or remains unchanged
If both level.x/ and iter.x/ are unchanged, then x/ D x/ If level.x/
Trang 19is unchanged and iter.x/ increases, then it increases by at least 1, and so
q.x/ q1.x/ 1
Finally, if the qth operation increases level.x/, it increases by at least 1, so that
the value of the term ˛.n/ level.x// x: rank drops by at least x: rank
Be-cause level.x/ increased, the value of iter.x/ might drop, but according to the
bound (21.2), the drop is by at most x: rank 1 Thus, the increase in
poten-tial due to the change in iter.x/ is less than the decrease in potenpoten-tial due to thechange in level.x/, and we conclude that q.x/ q1.x/ 1
Our final three lemmas show that the amortized cost of each MAKE-SET, LINK,and FIND-SET operation is O.˛.n// Recall from equation (17.2) that the amor-tized cost of each operation is its actual cost plus the increase in potential due tothe operation
Lemma 21.11
The amortized cost of each MAKE-SEToperation is O.1/
Proof Suppose that the qth operation is MAKE-SET.x/ This operation createsnode x with rank 0, so that q.x/ D 0 No other ranks or potentials change, and
so ˆq D ˆq1 Noting that the actual cost of the MAKE-SET operation is O.1/completes the proof
Lemma 21.12
The amortized cost of each LINKoperation is O.˛.n//
Proof Suppose that the qth operation is LINK.x; y/ The actual cost of the LINKoperation is O.1/ Without loss of generality, suppose that the LINKmakes y theparent of x
To determine the change in potential due to the LINK, we note that the onlynodes whose potentials may change are x, y, and the children of y just prior to theoperation We shall show that the only node whose potential can increase due tothe LINKis y, and that its increase is at most ˛.n/:
By Lemma 21.10, any node that is y’s child just before the LINKcannot haveits potential increase due to the LINK
From the definition of q.x/, we see that, since x was a root just before the qthoperation, q1.x/ D ˛.n/x:rank If x:rank D 0, then q.x/ D q1.x/ D 0.Otherwise,
q.x/ < ˛.n/ x:rank (by Corollary 21.9)
D q1.x/ ;
and so x’s potential decreases
Trang 20Because y is a root prior to the LINK, q1.y/ D ˛.n/ y:rank The LINK
operation leaves y as a root, and it either leaves y’s rank alone or it increases y’srank by 1 Therefore, either q.y/ D q1.y/ or q.y/ D q1.y/ C ˛.n/.The increase in potential due to the LINK operation, therefore, is at most ˛.n/.The amortized cost of the LINKoperation is O.1/ C ˛.n/ D O.˛.n//
Lemma 21.13
The amortized cost of each FIND-SEToperation is O.˛.n//
Proof Suppose that the qth operation is a FIND-SET and that the find path tains s nodes The actual cost of the FIND-SET operation is O.s/ We shallshow that no node’s potential increases due to the FIND-SET and that at leastmax.0; s ˛.n/ C 2// nodes on the find path have their potential decrease by
con-at least 1
To see that no node’s potential increases, we first appeal to Lemma 21.10 for all
nodes other than the root If x is the root, then its potential is ˛.n/ x: rank, which
does not change
Now we show that at least max.0; s ˛.n/ C 2// nodes have their potential
decrease by at least 1 Let x be a node on the find path such that x: rank > 0
and x is followed somewhere on the find path by another node y that is not a root,where level.y/ D level.x/ just before the FIND-SEToperation (Node y need not
immediately follow x on the find path.) All but at most ˛.n/ C 2 nodes on the find
path satisfy these constraints on x Those that do not satisfy them are the first node
on the find path (if it has rank 0), the last node on the path (i.e., the root), and thelast node w on the path for which level.w/ D k, for each k D 0; 1; 2; : : : ; ˛.n/ 1.Let us fix such a node x, and we shall show that x’s potential decreases by atleast 1 Let k D level.x/ D level.y/ Just prior to the path compression caused bythe FIND-SET, we have
x:p:rank A.iter.x//k .x:rank/ (by definition of iter.x/) ,
y:p:rank Ak.y:rank/ (by definition of level.y/) ,
y:rank x:p:rank (by Corollary 21.5 and because
y follows x on the find path) Putting these inequalities together and letting i be the value of iter.x/ before pathcompression, we have
y:p:rank Ak.y:rank/
Ak.x:p:rank/ (because Ak.j / is strictly increasing)
Ak.A.iter.x//k .x:rank//
D A.i C1/.x:rank/ :
Trang 21Because path compression will make x and y have the same parent, we know
that after path compression, x: p: rank D y: p: rank and that the path compression does not decrease y: p: rank Since x: rank does not change, after path compression
we have that x: p: rank A.i C1/k .x:rank/ Thus, path compression will cause
ei-ther iter.x/ to increase (to at least i C 1) or level.x/ to increase (which occurs if
iter.x/ increases to at least x: rank C 1) In either case, by Lemma 21.10, we have
q.x/ q1.x/ 1 Hence, x’s potential decreases by at least 1
The amortized cost of the FIND-SEToperation is the actual cost plus the change
in potential The actual cost is O.s/, and we have shown that the total potentialdecreases by at least max.0; s ˛.n/ C 2// The amortized cost, therefore, is atmost O.s/ s ˛.n/ C 2// D O.s/ s C O.˛.n// D O.˛.n//, since we canscale up the units of potential to dominate the constant hidden in O.s/
Putting the preceding lemmas together yields the following theorem
Theorem 21.14
A sequence of m MAKE-SET, UNION, and FIND-SEToperations, n of which areMAKE-SET operations, can be performed on a disjoint-set forest with union byrank and path compression in worst-case time O.m ˛.n//
Proof Immediate from Lemmas 21.7, 21.11, 21.12, and 21.13
Trang 22words, if x: rank > 0 and x: p is not a root, then level.x/ level.x: p/ Is the
professor correct?
21.4-6 ?
Consider the function ˛0.n/ D min fk W Ak.1/ lg.n C 1/g Show that ˛0.n/ 3for all practical values of n and, using Exercise 21.4-2, show how to modify thepotential-function argument to prove that we can perform a sequence of m MAKE-SET, UNION, and FIND-SEToperations, n of which are MAKE-SEToperations, on
a disjoint-set forest with union by rank and path compression in worst-case timeO.m ˛0.n//
Problems
21-1 Off-line minimum
The off-line minimum problem asks us to maintain a dynamic set T of elements
from the domain f1; 2; : : : ; ng under the operations INSERT and EXTRACT-MIN
We are given a sequence S of n INSERTand m EXTRACT-MIN calls, where eachkey in f1; 2; : : : ; ng is inserted exactly once We wish to determine which key
is returned by each EXTRACT-MIN call Specifically, we wish to fill in an array
extracted Œ1 : : m, where for i D 1; 2; : : : ; m, extractedŒi is the key returned by
the i th EXTRACT-MIN call The problem is “off-line” in the sense that we areallowed to process the entire sequence S before determining any of the returnedkeys
a In the following instance of the off-line minimum problem, each operation
INSERT.i / is represented by the value of i and each EXTRACT-MIN is resented by the letter E:
rep-4; 8; E; 3; E; 9; 2; 6; E; E; E; 1; 7; E; 5 :
Fill in the correct values in the extracted array.
To develop an algorithm for this problem, we break the sequence S into neous subsequences That is, we represent S by
homoge-I1; E; I2; E; I3; : : : ; Im; E; ImC1;
where each E represents a single EXTRACT-MIN call and each Ij represents a sibly empty) sequence of INSERTcalls For each subsequence Ij, we initially placethe keys inserted by these operations into a set Kj, which is empty if Ij is empty
(pos-We then do the following:
Trang 235 let l be the smallest value greater than j
for which set Klexists
6 Kl D Kj [ Kl, destroying Kj
7 return extracted
b Argue that the array extracted returned by OFF-LINE-MINIMUMis correct
c Describe how to implement OFF-LINE-MINIMUM efficiently with a set data structure Give a tight bound on the worst-case running time of yourimplementation
disjoint-21-2 Depth determination
In the depth-determination problem, we maintain a forest F D fTig of rootedtrees under three operations:
MAKE-TREE./ creates a tree whose only node is
FIND-DEPTH./ returns the depth of node within its tree
GRAFT.r; / makes node r, which is assumed to be the root of a tree, become thechild of node , which is assumed to be in a different tree than r but may or maynot itself be a root
a Suppose that we use a tree representation similar to a disjoint-set forest: : p
is the parent of node , except that : p D if is a root Suppose further
that we implement GRAFT.r; / by setting r:p D and FIND-DEPTH./ byfollowing the find path up to the root, returning a count of all nodes other than encountered Show that the worst-case running time of a sequence of m MAKE-TREE, FIND-DEPTH, and GRAFToperations is ‚.m2/
By using the union-by-rank and path-compression heuristics, we can reduce theworst-case running time We use the disjoint-set forest S D fSig, where eachset Si (which is itself a tree) corresponds to a tree Ti in the forest F The treestructure within a set Si, however, does not necessarily correspond to that of Ti Infact, the implementation of Si does not record the exact parent-child relationshipsbut nevertheless allows us to determine any node’s depth in Ti
The key idea is to maintain in each node a “pseudodistance” : d, which is
defined so that the sum of the pseudodistances along the simple path from to the
Trang 24root of its set Siequals the depth of in Ti That is, if the simple path from to itsroot in Si is 0; 1; : : : ; k, where 0 D and k is Si’s root, then the depth of
in Ti isPk
j D0j:d.
b Give an implementation of MAKE-TREE.
c Show how to modify FIND-SETto implement FIND-DEPTH Your tation should perform path compression, and its running time should be linear
implemen-in the length of the find path Make sure that your implementation updatespseudodistances correctly
d Show how to implement GRAFT.r; /, which combines the sets containing rand , by modifying the UNION and LINK procedures Make sure that yourimplementation updates pseudodistances correctly Note that the root of a set Si
is not necessarily the root of the corresponding tree Ti
e Give a tight bound on the worst-case running time of a sequence of m MTREE, FIND-DEPTH, and GRAFToperations, n of which are MAKE-TREEop-erations
AKE-21-3 Tarjan’s off-line least-common-ancestors algorithm
The least common ancestor of two nodes u and in a rooted tree T is the node w
that is an ancestor of both u and and that has the greatest depth in T In the
off-line least-common-ancestors problem, we are given a rooted tree T and an
arbitrary set P Dffu; gg of unordered pairs of nodes in T , and we wish to mine the least common ancestor of each pair in P
deter-To solve the off-line least-common-ancestors problem, the following procedure
performs a tree walk of T with the initial call LCA.T: root/ We assume that each
node is coloredWHITEprior to the walk
10 print “The least common ancestor of”
u “and” “is” FIND-SET./:ancestor
Trang 25a Argue that line 10 executes exactly once for each pairfu; g 2 P
b Argue that at the time of the call LCA.u/, the number of sets in the disjoint-set
data structure equals the depth of u in T
c Prove that LCA correctly prints the least common ancestor of u and for each
pairfu; g 2 P
d Analyze the running time of LCA, assuming that we use the implementation of
the disjoint-set data structure in Section 21.3
Chapter notes
Many of the important results for disjoint-set data structures are due at least in part
to R E Tarjan Using aggregate analysis, Tarjan [328, 330] gave the first tightupper bound in terms of the very slowly growing inverse y˛.m; n/ of Ackermann’sfunction (The function Ak.j / given in Section 21.4 is similar to Ackermann’sfunction, and the function ˛.n/ is similar to the inverse Both ˛.n/ and y˛.m; n/are at most 4 for all conceivable values of m and n.) An O.m lgn/ upper boundwas proven earlier by Hopcroft and Ullman [5, 179] The treatment in Section 21.4
is adapted from a later analysis by Tarjan [332], which is in turn based on an ysis by Kozen [220] Harfst and Reingold [161] give a potential-based version ofTarjan’s earlier bound
anal-Tarjan and van Leeuwen [333] discuss variants on the path-compression tic, including “one-pass methods,” which sometimes offer better constant factors
heuris-in their performance than do two-pass methods As with Tarjan’s earlier analyses
of the basic path-compression heuristic, the analyses by Tarjan and van Leeuwenare aggregate Harfst and Reingold [161] later showed how to make a small change
to the potential function to adapt their path-compression analysis to these one-passvariants Gabow and Tarjan [121] show that in certain applications, the disjoint-setoperations can be made to run in O.m/ time
Tarjan [329] showed that a lower bound of .m y˛.m; n// time is required foroperations on any disjoint-set data structure satisfying certain technical conditions.This lower bound was later generalized by Fredman and Saks [113], who showedthat in the worst case, .m y˛.m; n// lg n/-bit words of memory must be accessed
Trang 27Graph problems pervade computer science, and algorithms for working with themare fundamental to the field Hundreds of interesting computational problems arecouched in terms of graphs In this part, we touch on a few of the more significantones.
Chapter 22 shows how we can represent a graph in a computer and then discussesalgorithms based on searching a graph using either breadth-first search or depth-first search The chapter gives two applications of depth-first search: topologicallysorting a directed acyclic graph and decomposing a directed graph into its stronglyconnected components
Chapter 23 describes how to compute a minimum-weight spanning tree of agraph: the least-weight way of connecting all of the vertices together when eachedge has an associated weight The algorithms for computing minimum spanningtrees serve as good examples of greedy algorithms (see Chapter 16)
Chapters 24 and 25 consider how to compute shortest paths between verticeswhen each edge has an associated length or “weight.” Chapter 24 shows how tofind shortest paths from a given source vertex to all other vertices, and Chapter 25examines methods to compute shortest paths between every pair of vertices.Finally, Chapter 26 shows how to compute a maximum flow of material in a flownetwork, which is a directed graph having a specified source vertex of material, aspecified sink vertex, and specified capacities for the amount of material that cantraverse each directed edge This general problem arises in many forms, and agood algorithm for computing maximum flows can help solve a variety of relatedproblems efficiently
Trang 28When we characterize the running time of a graph algorithm on a given graph
G D V; E/, we usually measure the size of the input in terms of the number ofvertices jV j and the number of edges jEj of the graph That is, we describe thesize of the input with two parameters, not just one We adopt a common notationalconvention for these parameters Inside asymptotic notation (such as O-notation
or ‚-notation), and only inside such notation, the symbol V denotes jV j andthe symbol E denotes jEj For example, we might say, “the algorithm runs intime O.VE/,” meaning that the algorithm runs in time O.jV j jEj/ This conven-tion makes the running-time formulas easier to read, without risk of ambiguity.Another convention we adopt appears in pseudocode We denote the vertex set
of a graph G by G: V and its edge set by G: E That is, the pseudocode views vertex
and edge sets as attributes of a graph
Trang 29This chapter presents methods for representing a graph and for searching a graph.Searching a graph means systematically following the edges of the graph so as tovisit the vertices of the graph A graph-searching algorithm can discover muchabout the structure of a graph Many algorithms begin by searching their inputgraph to obtain this structural information Several other graph algorithms elabo-rate on basic graph searching Techniques for searching a graph lie at the heart ofthe field of graph algorithms.
Section 22.1 discusses the two most common computational representations ofgraphs: as adjacency lists and as adjacency matrices Section 22.2 presents a sim-ple graph-searching algorithm called breadth-first search and shows how to cre-ate a breadth-first tree Section 22.3 presents depth-first search and proves somestandard results about the order in which depth-first search visits vertices Sec-tion 22.4 provides our first real application of depth-first search: topologically sort-ing a directed acyclic graph A second application of depth-first search, finding thestrongly connected components of a directed graph, is the topic of Section 22.5
22.1 Representations of graphs
We can choose between two standard ways to represent a graph G D V; E/:
as a collection of adjacency lists or as an adjacency matrix Either way applies
to both directed and undirected graphs Because the adjacency-list representation
provides a compact way to represent sparse graphs—those for whichjEj is muchless than jV j2—it is usually the method of choice Most of the graph algorithmspresented in this book assume that an input graph is represented in adjacency-list form We may prefer an adjacency-matrix representation, however, when the
graph is dense—jEj is close to jV j2—or when we need to be able to tell quickly
if there is an edge connecting two given vertices For example, two of the all-pairs
Trang 301 2
3 4 5
1 2 3 4 5
1 2 2
1 2 3 4 5
1 2 3 4 5
5 6 2 4 6
1 2 3 4 5
Figure 22.2 Two representations of a directed graph (a) A directed graph G with 6 vertices and 8 edges (b) An adjacency-list representation of G (c) The adjacency-matrix representation of G.
shortest-paths algorithms presented in Chapter 25 assume that their input graphsare represented by adjacency matrices
The adjacency-list representation of a graph G D V; E/ consists of an
ar-ray Adj ofjV j lists, one for each vertex in V For each u 2 V , the adjacency list
AdjŒu contains all the vertices such that there is an edge u; / 2 E That is,
AdjŒu consists of all the vertices adjacent to u in G (Alternatively, it may containpointers to these vertices.) Since the adjacency lists represent the edges of a graph,
in pseudocode we treat the array Adj as an attribute of the graph, just as we treat the edge set E In pseudocode, therefore, we will see notation such as G: AdjŒu.
Figure 22.1(b) is an adjacency-list representation of the undirected graph in ure 22.1(a) Similarly, Figure 22.2(b) is an adjacency-list representation of thedirected graph in Figure 22.2(a)
Fig-If G is a directed graph, the sum of the lengths of all the adjacency lists isjEj,
since an edge of the form u; / is represented by having appear in AdjŒu If G is
Trang 31an undirected graph, the sum of the lengths of all the adjacency lists is 2jEj, since
if u; / is an undirected edge, then u appears in ’s adjacency list and vice versa.For both directed and undirected graphs, the adjacency-list representation has thedesirable property that the amount of memory it requires is ‚.V C E/
We can readily adapt adjacency lists to represent weighted graphs, that is, graphs for which each edge has an associated weight, typically given by a weight function
w W E ! R For example, let G D V; E/ be a weighted graph with weightfunction w We simply store the weight w.u; / of the edge u; / 2 E withvertex in u’s adjacency list The adjacency-list representation is quite robust inthat we can modify it to support many other graph variants
A potential disadvantage of the adjacency-list representation is that it provides
no quicker way to determine whether a given edge u; / is present in the graph
than to search for in the adjacency list AdjŒu An adjacency-matrix
representa-tion of the graph remedies this disadvantage, but at the cost of using asymptoticallymore memory (See Exercise 22.1-8 for suggestions of variations on adjacency liststhat permit faster edge lookup.)
For the adjacency-matrix representation of a graph G D V; E/, we assume
that the vertices are numbered 1; 2; : : : ;jV j in some arbitrary manner Then theadjacency-matrix representation of a graph G consists of a jV j jV j matrix
In some applications, it pays to store only the entries on and above the diagonal ofthe adjacency matrix, thereby cutting the memory needed to store the graph almost
in half
Like the adjacency-list representation of a graph, an adjacency matrix can sent a weighted graph For example, if G D V; E/ is a weighted graph with edge-weight function w, we can simply store the weight w.u; / of the edge u; / 2 E
repre-as the entry in row u and column of the adjacency matrix If an edge does notexist, we can store aNILvalue as its corresponding matrix entry, though for manyproblems it is convenient to use a value such as 0 or 1
Although the adjacency-list representation is asymptotically at least as efficient as the adjacency-matrix representation, adjacency matrices are simpler,and so we may prefer them when graphs are reasonably small Moreover, adja-
Trang 32space-cency matrices carry a further advantage for unweighted graphs: they require onlyone bit per entry.
Representing attributes
Most algorithms that operate on graphs need to maintain attributes for vertices
and/or edges We indicate these attributes using our usual notation, such as : d
for an attribute d of a vertex When we indicate edges as pairs of vertices, weuse the same style of notation For example, if edges have an attribute f , then we
denote this attribute for edge u; / by u; /: f For the purpose of presenting and
understanding algorithms, our attribute notation suffices
Implementing vertex and edge attributes in real programs can be another storyentirely There is no one best way to store and access vertex and edge attributes.For a given situation, your decision will likely depend on the programming lan-guage you are using, the algorithm you are implementing, and how the rest of yourprogram uses the graph If you represent a graph using adjacency lists, one designrepresents vertex attributes in additional arrays, such as an array d Œ1 : :jV j that
parallels the Adj array If the vertices adjacent to u are in AdjŒu, then what we call the attribute u: d would actually be stored in the array entry d Œu Many other ways
of implementing attributes are possible For example, in an object-oriented gramming language, vertex attributes might be represented as instance variableswithin a subclass of aVertexclass
pro-Exercises
22.1-1
Given an adjacency-list representation of a directed graph, how long does it take
to compute the out-degree of every vertex? How long does it take to compute thein-degrees?
22.1-2
Give an adjacency-list representation for a complete binary tree on 7 vertices Give
an equivalent adjacency-matrix representation Assume that vertices are numberedfrom 1 to 7 as in a binary heap
22.1-3
The transpose of a directed graph G D V; E/ is the graph GT D V; ET/, where
ET D f.; u/ 2 V V W u; / 2 Eg Thus, GT is G with all its edges reversed.Describe efficient algorithms for computing GT from G, for both the adjacency-list and adjacency-matrix representations of G Analyze the running times of youralgorithms
Trang 33The square of a directed graph G D V; E/ is the graph G2 D V; E2/ such that.u; / 2 E2if and only G contains a path with at most two edges between u and .Describe efficient algorithms for computing G2 from G for both the adjacency-list and adjacency-matrix representations of G Analyze the running times of youralgorithms
The incidence matrix of a directed graph G D V; E/ with no self-loops is a
jV j jEj matrix B D bij/ such that
bij D
1 if edge j leaves vertex i ;
1 if edge j enters vertex i ;
0 otherwise :
Describe what the entries of the matrix product BBT represent, where BT is thetranspose of B
22.1-8
Suppose that instead of a linked list, each array entry AdjŒu is a hash table
contain-ing the vertices for which u; / 2 E If all edge lookups are equally likely, what
is the expected time to determine whether an edge is in the graph? What tages does this scheme have? Suggest an alternate data structure for each edge listthat solves these problems Does your alternative have disadvantages compared tothe hash table?
Trang 34disadvan-22.2 Breadth-first search
Breadth-first search is one of the simplest algorithms for searching a graph and
the archetype for many important graph algorithms Prim’s tree algorithm (Section 23.2) and Dijkstra’s single-source shortest-paths algorithm(Section 24.3) use ideas similar to those in breadth-first search
minimum-spanning-Given a graph G D V; E/ and a distinguished source vertex s, breadth-first
search systematically explores the edges of G to “discover” every vertex that isreachable from s It computes the distance (smallest number of edges) from s
to each reachable vertex It also produces a “breadth-first tree” with root s thatcontains all reachable vertices For any vertex reachable from s, the simple path
in the breadth-first tree from s to corresponds to a “shortest path” from s to
in G, that is, a path containing the smallest number of edges The algorithm works
on both directed and undirected graphs
Breadth-first search is so named because it expands the frontier between ered and undiscovered vertices uniformly across the breadth of the frontier That
discov-is, the algorithm discovers all vertices at distance k from s before discovering anyvertices at distance k C 1
To keep track of progress, breadth-first search colors each vertex white, gray, orblack All vertices start out white and may later become gray and then black A
vertex is discovered the first time it is encountered during the search, at which time
it becomes nonwhite Gray and black vertices, therefore, have been discovered, butbreadth-first search distinguishes between them to ensure that the search proceeds
in a breadth-first manner.1 If u; / 2 E and vertex u is black, then vertex
is either gray or black; that is, all vertices adjacent to black vertices have beendiscovered Gray vertices may have some adjacent white vertices; they representthe frontier between discovered and undiscovered vertices
Breadth-first search constructs a breadth-first tree, initially containing only itsroot, which is the source vertex s Whenever the search discovers a white vertex
in the course of scanning the adjacency list of an already discovered vertex u, the
vertex and the edge u; / are added to the tree We say that u is the predecessor
or parent of in the breadth-first tree Since a vertex is discovered at most once, it
has at most one parent Ancestor and descendant relationships in the breadth-firsttree are defined relative to the root s as usual: if u is on the simple path in the treefrom the root s to vertex , then u is an ancestor of and is a descendant of u
1 We distinguish between gray and black vertices to help us understand how breadth-first search erates In fact, as Exercise 22.2-3 shows, we would get the same result even if we did not distinguish between gray and black vertices.
Trang 35op-The breadth-first-search procedure BFS below assumes that the input graph
G D V; E/ is represented using adjacency lists It attaches several additionalattributes to each vertex in the graph We store the color of each vertex u 2 V
in the attribute u: color and the predecessor of u in the attribute u: If u has no
predecessor (for example, if u D s or u has not been discovered), then u: DNIL.
The attribute u: d holds the distance from the source s to vertex u computed by the
algorithm The algorithm also uses a first-in, first-out queue Q (see Section 10.1)
to manage the set of gray vertices
Figure 22.3 illustrates the progress of BFS on a sample graph
The procedure BFS works as follows With the exception of the source vertex s,
lines 1–4 paint every vertex white, set u: d to be infinity for each vertex u, and set
the parent of every vertex to beNIL Line 5 paints s gray, since we consider it to be
discovered as the procedure begins Line 6 initializes s: d to 0, and line 7 sets the
predecessor of the source to beNIL Lines 8–9 initialize Q to the queue containingjust the vertex s
The while loop of lines 10–18 iterates as long as there remain gray vertices,
which are discovered vertices that have not yet had their adjacency lists fully
ex-amined This while loop maintains the following invariant:
At the test in line 10, the queue Q consists of the set of gray vertices
Trang 360 1
3
Q
2 2 1
2
2 1
3
;
Figure 22.3 The operation of BFS on an undirected graph Tree edges are shown shaded as they
are produced by BFS The value of u: d appears within each vertex u The queue Q is shown at the
beginning of each iteration of the while loop of lines 10–18 Vertex distances appear below vertices
in the queue.
Although we won’t use this loop invariant to prove correctness, it is easy to seethat it holds prior to the first iteration and that each iteration of the loop maintainsthe invariant Prior to the first iteration, the only gray vertex, and the only vertex
in Q, is the source vertex s Line 11 determines the gray vertex u at the head of
the queue Q and removes it from Q The for loop of lines 12–17 considers each
vertex in the adjacency list of u If is white, then it has not yet been discovered,and the procedure discovers it by executing lines 14–17 The procedure paints
vertex gray, sets its distance : d to u: dC1, records u as its parent : , and places
it at the tail of the queue Q Once the procedure has examined all the vertices on u’s
Trang 37adjacency list, it blackens u in line 18 The loop invariant is maintained becausewhenever a vertex is painted gray (in line 14) it is also enqueued (in line 17), andwhenever a vertex is dequeued (in line 11) it is also painted black (in line 18).The results of breadth-first search may depend upon the order in which the neigh-bors of a given vertex are visited in line 12: the breadth-first tree may vary, but thedistances d computed by the algorithm will not (See Exercise 22.2-5.)
Analysis
Before proving the various properties of breadth-first search, we take on the what easier job of analyzing its running time on an input graph G D V; E/ Weuse aggregate analysis, as we saw in Section 17.1 After initialization, breadth-firstsearch never whitens a vertex, and thus the test in line 13 ensures that each vertex
some-is enqueued at most once, and hence dequeued at most once The operations ofenqueuing and dequeuing take O.1/ time, and so the total time devoted to queueoperations is O.V / Because the procedure scans the adjacency list of each vertexonly when the vertex is dequeued, it scans each adjacency list at most once Sincethe sum of the lengths of all the adjacency lists is ‚.E/, the total time spent inscanning adjacency lists is O.E/ The overhead for initialization is O.V /, andthus the total running time of the BFS procedure is O.V C E/ Thus, breadth-firstsearch runs in time linear in the size of the adjacency-list representation of G
Shortest paths
At the beginning of this section, we claimed that breadth-first search finds the tance to each reachable vertex in a graph G D V; E/ from a given source vertex
dis-s 2 V Define the dis-shortedis-st-path didis-stance ı.dis-s; / from dis-s to adis-s the minimum
num-ber of edges in any path from vertex s to vertex ; if there is no path from s to ,
then ı.s; / D 1 We call a path of length ı.s; / from s to a shortest path2
from s to Before showing that breadth-first search correctly computes path distances, we investigate an important property of shortest-path distances
shortest-2 In Chapters 24 and 25, we shall generalize our study of shortest paths to weighted graphs, in which every edge has a real-valued weight and the weight of a path is the sum of the weights of its con- stituent edges The graphs considered in the present chapter are unweighted or, equivalently, all edges have unit weight.
Trang 38Lemma 22.1
Let G D V; E/ be a directed or undirected graph, and let s 2 V be an arbitraryvertex Then, for any edge u; / 2 E,
ı.s; / ı.s; u/ C 1 :
Proof If u is reachable from s, then so is In this case, the shortest path from s
to cannot be longer than the shortest path from s to u followed by the edge u; /,and thus the inequality holds If u is not reachable from s, then ı.s; u/ D 1, andthe inequality holds
We want to show that BFS properly computes : d D ı.s; / for each tex 2 V We first show that : d bounds ı.s; / from above.
ver-Lemma 22.2
Let G D V; E/ be a directed or undirected graph, and suppose that BFS is run
on G from a given source vertex s 2 V Then upon termination, for each
ver-tex 2 V , the value : d computed by BFS satisfies : d ı.s; /.
Proof We use induction on the number of ENQUEUE operations Our inductive
hypothesis is that : d ı.s; / for all 2 V
The basis of the induction is the situation immediately after enqueuing s in line 9
of BFS The inductive hypothesis holds here, because s: d D 0 D ı.s; s/ and
:d D 1 ı.s; / for all 2 V fsg.
For the inductive step, consider a white vertex that is discovered during the
search from a vertex u The inductive hypothesis implies that u: d ı.s; u/ From
the assignment performed by line 15 and from Lemma 22.1, we obtain
:d D u:d C 1
ı.s; u/ C 1
ı.s; / :Vertex is then enqueued, and it is never enqueued again because it is also grayed
and the then clause of lines 14–17 is executed only for white vertices Thus, the
value of : d never changes again, and the inductive hypothesis is maintained.
To prove that : d D ı.s; /, we must first show more precisely how the queue Q
operates during the course of BFS The next lemma shows that at all times, thequeue holds at most two distinct d values
Trang 39Lemma 22.3
Suppose that during the execution of BFS on a graph G D V; E/, the queue Qcontains the vertices h1; 2; : : : ; ri, where 1is the head of Q and r is the tail.Then, r:d 1:d C 1 and i:d i C1:d for i D 1; 2; : : : ; r 1.
Proof The proof is by induction on the number of queue operations Initially,when the queue contains only s, the lemma certainly holds
For the inductive step, we must prove that the lemma holds after both dequeuingand enqueuing a vertex If the head 1of the queue is dequeued, 2 becomes thenew head (If the queue becomes empty, then the lemma holds vacuously.) By theinductive hypothesis, 1:d 2:d But then we have r:d 1:d C 1 2:d C 1,
and the remaining inequalities are unaffected Thus, the lemma follows with 2asthe head
In order to understand what happens upon enqueuing a vertex, we need to amine the code more closely When we enqueue a vertex in line 17 of BFS, itbecomes rC1 At that time, we have already removed vertex u, whose adjacencylist is currently being scanned, from the queue Q, and by the inductive hypothesis,the new head 1has 1:d u:d Thus, rC1:d D :d D u:d C1 1:d C1 From
ex-the inductive hypoex-thesis, we also have r:d u:d C 1, and so r:d u:d C 1 D
:d D rC1:d, and the remaining inequalities are unaffected Thus, the lemma
follows when is enqueued
The following corollary shows that the d values at the time that vertices areenqueued are monotonically increasing over time
dis-Theorem 22.5 (Correctness of breadth-first search)
Let G D V; E/ be a directed or undirected graph, and suppose that BFS is run
on G from a given source vertex s 2 V Then, during its execution, BFS discoversevery vertex 2 V that is reachable from the source s, and upon termination,
:d D ı.s; / for all 2 V Moreover, for any vertex ¤ s that is reachable
Trang 40from s, one of the shortest paths from s to is a shortest path from s to : followed by the edge : ; /.
Proof Assume, for the purpose of contradiction, that some vertex receives a dvalue not equal to its shortest-path distance Let be the vertex with min-imum ı.s; / that receives such an incorrect d value; clearly ¤ s By
Lemma 22.2, : d ı.s; /, and thus we have that : d > ı.s; / Vertex must be reachable from s, for if it is not, then ı.s; / D 1 : d Let u be the vertex im-
mediately preceding on a shortest path from s to , so that ı.s; / D ı.s; u/ C 1
Because ı.s; u/ < ı.s; /, and because of how we chose , we have u: d D ı.s; u/.
Putting these properties together, we have
Now consider the time when BFS chooses to dequeue vertex u from Q inline 11 At this time, vertex is either white, gray, or black We shall showthat in each of these cases, we derive a contradiction to inequality (22.1) If is
white, then line 15 sets : d D u: d C 1, contradicting inequality (22.1) If is
black, then it was already removed from the queue and, by Corollary 22.4, we have
:d u:d, again contradicting inequality (22.1) If is gray, then it was painted
gray upon dequeuing some vertex w, which was removed from Q earlier than u
and for which : d D w: d C 1 By Corollary 22.4, however, w: d u: d, and so we have : d D w: d C 1 u: d C 1, once again contradicting inequality (22.1) Thus we conclude that : d D ı.s; / for all 2 V All vertices reachable from s must be discovered, for otherwise they would have 1 D : d > ı.s; / To conclude the proof of the theorem, observe that if : D u, then : d D u: d C 1.
Thus, we can obtain a shortest path from s to by taking a shortest path from s
to : and then traversing the edge : ; /