The pseudocode below determines the lowest common ancestor of each pair in
P, given the root
r of a tree in which the children of node
n are in the set
n.children. For this offline algorithm, the set
P must be specified in advance. It uses the
MakeSet,
Find, and
Union functions of a
disjoint-set data structure.
MakeSet(u) removes
u to a singleton set,
Find(u) returns the standard representative of the set containing
u, and
Union(u,v) merges the set containing
u with the set containing
v. TarjanOLCA(
r) is first called on the root
r.
function TarjanOLCA(u)
is MakeSet(u) u.ancestor := u
for each v
in u.children
do TarjanOLCA(v) Union(u, v) Find(u).ancestor := u u.color := black
for each v
such that {u, v}
in P
do if v.color == black
then print "Tarjan's Lowest Common Ancestor of " + u + " and " + v + " is " + Find(v).ancestor + "." Each node is initially white, and is colored black after it and all its children have been visited. For each node pair
{u,v} to be investigated: • '
When v
is already black' (viz. when
v comes before
u in a post-order traversal of the tree): After
u is colored black, the lowest common ancestor of this pair is available as
Find(v).ancestor, but only while the LCA of
u and
v is not colored black. •
Otherwise: Once
v is colored black, the LCA will be available as
Find(u).ancestor, while the LCA is not colored black. According to the time complexity is O((m + n)a(m + n, n)), where m is the number of edges and n the number of vertices and a is the inverse Ackerman function,
provided that the time to find the vertex pairs corresponding to u takes constant time per vertex. The paper recommends using an
adjacency list (called adjacency structure in the paper). For reference, here are optimized versions of
MakeSet,
Find, and
Union for a
disjoint-set forest:
function MakeSet(x)
is x.parent := x x.rank := 1
function Union(x, y)
is xRoot := Find(x) yRoot := Find(y)
if xRoot.rank > yRoot.rank
then yRoot.parent := xRoot
else if xRoot.rank < yRoot.rank
then xRoot.parent := yRoot
else if xRoot.rank == yRoot.rank
then yRoot.parent := xRoot xRoot.rank := xRoot.rank + 1
function Find(x)
is if x.parent != x
then x.parent := Find(x.parent)
return x.parent ==Speeding up the algorithm==