Add Tarjan's algorithm
This commit is contained in:
parent
479a6bc2f9
commit
c1154d9147
124
chapter18.tex
124
chapter18.tex
|
@ -939,7 +939,7 @@ processes each query before receiving the next query.
|
||||||
However, in many problems, the online
|
However, in many problems, the online
|
||||||
property is not necessary.
|
property is not necessary.
|
||||||
In this section, we focus on \emph{offline} algorithms
|
In this section, we focus on \emph{offline} algorithms
|
||||||
that are given a collection of queries that can be
|
that are given a set of queries that can be
|
||||||
processed in any order.
|
processed in any order.
|
||||||
It is often easier to design an offline algorithm
|
It is often easier to design an offline algorithm
|
||||||
compared to an online algorithm.
|
compared to an online algorithm.
|
||||||
|
@ -1138,9 +1138,119 @@ when $a$ and $b$ are C++ standard library data structures.
|
||||||
|
|
||||||
\subsubsection{Lowest common ancestors}
|
\subsubsection{Lowest common ancestors}
|
||||||
|
|
||||||
It turns out that we can also process a collection of
|
There is also an offline algorithm
|
||||||
lowest common ancestor queries using an offline algorithm\footnote{This
|
for processing a set of
|
||||||
algorithm was discovered by R. E. Tarjan in 1979 \cite{tar79}.}.
|
lowest common ancestor queries\footnote{This
|
||||||
This algorithm is based on the union-find data structure
|
algorithm was published by R. E. Tarjan in 1979 \cite{tar79}.}.
|
||||||
(see 15.2), and it is easier to implement than the
|
The algorithm is based on the union-find data structure
|
||||||
previous algorithms presented in this chapter.
|
(see Chapter 15.2), and the benefit of the algorithm is
|
||||||
|
that it is easier to implement than the
|
||||||
|
algorithms discussed earlier in this chapter.
|
||||||
|
|
||||||
|
The algorithm is given as input a set of pairs of nodes,
|
||||||
|
and it determines for each such pair the
|
||||||
|
lowest common ancestor.
|
||||||
|
The algorithm performs a depth-first tree traversal
|
||||||
|
and maintains disjoint sets of nodes.
|
||||||
|
Initially, each node belongs to a separate set.
|
||||||
|
For each set, we also maintain the highest node in the
|
||||||
|
tree that belongs to the set.
|
||||||
|
|
||||||
|
When the algorithm visits a node $x$,
|
||||||
|
it goes through all nodes $y$ such that
|
||||||
|
the lowest common ancestor of $x$ and $y$
|
||||||
|
has to be found.
|
||||||
|
If $y$ has already been visited,
|
||||||
|
the algorithm reports that the
|
||||||
|
lowest common ancestor of $x$ and $y$
|
||||||
|
is the highest node in the set of $y$.
|
||||||
|
Then, after processing the subtree of $x$,
|
||||||
|
the algorithm combines the sets of $x$ and its parent.
|
||||||
|
|
||||||
|
For example, assume that we would like the lowest
|
||||||
|
common ancestor of node pairs $(5,8)$
|
||||||
|
and $(2,7)$ in the following tree:
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}[scale=0.85]
|
||||||
|
\node[draw, circle] (1) at (0,3) {$1$};
|
||||||
|
\node[draw, circle] (2) at (2,1) {$4$};
|
||||||
|
\node[draw, circle] (3) at (-2,1) {$2$};
|
||||||
|
\node[draw, circle] (4) at (0,1) {$3$};
|
||||||
|
\node[draw, circle] (5) at (2,-1) {$7$};
|
||||||
|
\node[draw, circle] (6) at (-3,-1) {$5$};
|
||||||
|
\node[draw, circle] (7) at (-1,-1) {$6$};
|
||||||
|
\node[draw, circle] (8) at (-1,-3) {$8$};
|
||||||
|
\path[draw,thick,-] (1) -- (2);
|
||||||
|
\path[draw,thick,-] (1) -- (3);
|
||||||
|
\path[draw,thick,-] (1) -- (4);
|
||||||
|
\path[draw,thick,-] (2) -- (5);
|
||||||
|
\path[draw,thick,-] (3) -- (6);
|
||||||
|
\path[draw,thick,-] (3) -- (7);
|
||||||
|
\path[draw,thick,-] (7) -- (8);
|
||||||
|
\end{tikzpicture}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
In the following pictures, gray nodes denote visited nodes
|
||||||
|
and dashed groups of nodes belong to the same set.
|
||||||
|
When the algorithm visits node 8, it notices that
|
||||||
|
node 5 has been visited and the highest node
|
||||||
|
in its set is 2. Thus, the lowest common ancestor
|
||||||
|
of nodes 5 and 8 is 2:
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}[scale=0.85]
|
||||||
|
\node[draw, circle, fill=lightgray] (1) at (0,3) {$1$};
|
||||||
|
\node[draw, circle] (2) at (2,1) {$4$};
|
||||||
|
\node[draw, circle, fill=lightgray] (3) at (-2,1) {$2$};
|
||||||
|
\node[draw, circle] (4) at (0,1) {$3$};
|
||||||
|
\node[draw, circle] (5) at (2,-1) {$7$};
|
||||||
|
\node[draw, circle, fill=lightgray] (6) at (-3,-1) {$5$};
|
||||||
|
\node[draw, circle, fill=lightgray] (7) at (-1,-1) {$6$};
|
||||||
|
\node[draw, circle, fill=gray] (8) at (-1,-3) {$8$};
|
||||||
|
\path[draw,thick,-] (1) -- (2);
|
||||||
|
\path[draw,thick,-] (1) -- (3);
|
||||||
|
\path[draw,thick,-] (1) -- (4);
|
||||||
|
\path[draw,thick,-] (2) -- (5);
|
||||||
|
\path[draw,thick,-] (3) -- (6);
|
||||||
|
\path[draw,thick,-] (3) -- (7);
|
||||||
|
\path[draw,thick,-] (7) -- (8);
|
||||||
|
|
||||||
|
\draw [red,thick,dashed,line width=2pt,rotate around={-28:(-2,0)}] (-2.9,1.5) rectangle (-1.9,-2);
|
||||||
|
|
||||||
|
|
||||||
|
\draw [red,thick,dashed,line width=2pt] (-1.5,-0.5) rectangle (-0.5,-1.5);
|
||||||
|
\draw [red,thick,dashed,line width=2pt] (-1.5,-2.5) rectangle (-0.5,-3.5);
|
||||||
|
|
||||||
|
\draw [red,thick,dashed,line width=2pt] (0.5,3.5) rectangle (-0.5,2.5);
|
||||||
|
\draw [red,thick,dashed,line width=2pt] (0.5,1.5) rectangle (-0.5,0.5);
|
||||||
|
\draw [red,thick,dashed,line width=2pt] (2.5,1.5) rectangle (1.5,0.5);
|
||||||
|
\draw [red,thick,dashed,line width=2pt] (2.5,-0.5) rectangle (1.5,-1.5);
|
||||||
|
\end{tikzpicture}
|
||||||
|
\end{center}
|
||||||
|
|
||||||
|
Later, when visiting node 7,
|
||||||
|
the algorithm determines that
|
||||||
|
the lowest common ancestor of nodes 2 and 7 is 1:
|
||||||
|
\begin{center}
|
||||||
|
\begin{tikzpicture}[scale=0.85]
|
||||||
|
\node[draw, circle, fill=lightgray] (1) at (0,3) {$1$};
|
||||||
|
\node[draw, circle, fill=lightgray] (2) at (2,1) {$4$};
|
||||||
|
\node[draw, circle, fill=lightgray] (3) at (-2,1) {$2$};
|
||||||
|
\node[draw, circle, fill=lightgray] (4) at (0,1) {$3$};
|
||||||
|
\node[draw, circle, fill=gray] (5) at (2,-1) {$7$};
|
||||||
|
\node[draw, circle, fill=lightgray] (6) at (-3,-1) {$5$};
|
||||||
|
\node[draw, circle, fill=lightgray] (7) at (-1,-1) {$6$};
|
||||||
|
\node[draw, circle, fill=lightgray] (8) at (-1,-3) {$8$};
|
||||||
|
\path[draw,thick,-] (1) -- (2);
|
||||||
|
\path[draw,thick,-] (1) -- (3);
|
||||||
|
\path[draw,thick,-] (1) -- (4);
|
||||||
|
\path[draw,thick,-] (2) -- (5);
|
||||||
|
\path[draw,thick,-] (3) -- (6);
|
||||||
|
\path[draw,thick,-] (3) -- (7);
|
||||||
|
\path[draw,thick,-] (7) -- (8);
|
||||||
|
|
||||||
|
\draw [red,thick,dashed,line width=2pt] (0.5,3.5) rectangle (-3.5,-3.5);
|
||||||
|
\draw [red,thick,dashed,line width=2pt] (2.5,1.5) rectangle (1.5,0.5);
|
||||||
|
\draw [red,thick,dashed,line width=2pt] (2.5,-0.5) rectangle (1.5,-1.5);
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
||||||
|
\end{center}
|
||||||
|
|
5
list.tex
5
list.tex
|
@ -352,6 +352,11 @@
|
||||||
Efficiency of a good but not linear set union algorithm.
|
Efficiency of a good but not linear set union algorithm.
|
||||||
\emph{Journal of the ACM}, 22(2):215--225, 1975.
|
\emph{Journal of the ACM}, 22(2):215--225, 1975.
|
||||||
|
|
||||||
|
\bibitem{tar79}
|
||||||
|
R. E. Tarjan.
|
||||||
|
Applications of path compression on balanced trees.
|
||||||
|
\emph{Journal of the ACM}, 26(4):690--715, 1979.
|
||||||
|
|
||||||
\bibitem{tar84}
|
\bibitem{tar84}
|
||||||
R. E. Tarjan and U. Vishkin.
|
R. E. Tarjan and U. Vishkin.
|
||||||
Finding biconnected componemts and computing tree functions in logarithmic parallel time.
|
Finding biconnected componemts and computing tree functions in logarithmic parallel time.
|
||||||
|
|
Loading…
Reference in New Issue