Improve language

This commit is contained in:
Antti H S Laaksonen 2017-05-07 21:18:56 +03:00
parent 7aad9cc8d9
commit 5a298088b9
10 changed files with 244 additions and 242 deletions

View File

@ -22,8 +22,7 @@ and study different ways to represent graphs in algorithms.
\index{edge} \index{edge}
A \key{graph} consists of \key{nodes} A \key{graph} consists of \key{nodes}
and \key{edges} between them. and \key{edges}. In this book,
In this book,
the variable $n$ denotes the number of nodes the variable $n$ denotes the number of nodes
in a graph, and the variable $m$ denotes in a graph, and the variable $m$ denotes
the number of edges. the number of edges.
@ -57,7 +56,7 @@ through edges of the graph.
The \key{length} of a path is the number of The \key{length} of a path is the number of
edges in it. edges in it.
For example, the above graph contains For example, the above graph contains
the path $1 \rightarrow 3 \rightarrow 4 \rightarrow 5$ a path $1 \rightarrow 3 \rightarrow 4 \rightarrow 5$
from node 1 to node 5: from node 1 to node 5:
\begin{center} \begin{center}
@ -87,7 +86,7 @@ from node 1 to node 5:
A path is a \key{cycle} if the first and last A path is a \key{cycle} if the first and last
node is the same. node is the same.
For example, the above graph contains For example, the above graph contains
the cycle $1 \rightarrow 3 \rightarrow 4 \rightarrow 1$. a cycle $1 \rightarrow 3 \rightarrow 4 \rightarrow 1$.
A path is \key{simple} if each node appears A path is \key{simple} if each node appears
at most once in the path. at most once in the path.
@ -106,7 +105,7 @@ at most once in the path.
\index{connected graph} \index{connected graph}
A graph is \key{connected} if there is path A graph is \key{connected} if there is a path
between any two nodes. between any two nodes.
For example, the following graph is connected: For example, the following graph is connected:
\begin{center} \begin{center}
@ -175,7 +174,7 @@ $\{8\}$.
A \key{tree} is a connected graph A \key{tree} is a connected graph
that consists of $n$ nodes and $n-1$ edges. that consists of $n$ nodes and $n-1$ edges.
There is a unique path There is a unique path
between any two nodes in a tree. between any two nodes of a tree.
For example, the following graph is a tree: For example, the following graph is a tree:
\begin{center} \begin{center}
@ -220,7 +219,7 @@ For example, the following graph is directed:
\end{center} \end{center}
The above graph contains The above graph contains
the path $3 \rightarrow 1 \rightarrow 2 \rightarrow 5$ a path $3 \rightarrow 1 \rightarrow 2 \rightarrow 5$
from node $3$ to node $5$, from node $3$ to node $5$,
but there is no path from node $5$ to node $3$. but there is no path from node $5$ to node $3$.
@ -230,7 +229,7 @@ but there is no path from node $5$ to node $3$.
In a \key{weighted} graph, each edge is assigned In a \key{weighted} graph, each edge is assigned
a \key{weight}. a \key{weight}.
Often the weights are interpreted as edge lengths. The weights are often interpreted as edge lengths.
For example, the following graph is weighted: For example, the following graph is weighted:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -249,10 +248,10 @@ For example, the following graph is weighted:
\end{center} \end{center}
The length of a path in a weighted graph The length of a path in a weighted graph
is the sum of edge weights on the path. is the sum of the edge weights on the path.
For example, in the above graph, For example, in the above graph,
the length of the path the length of the path
$1 \rightarrow 2 \rightarrow 5$ is $12$ $1 \rightarrow 2 \rightarrow 5$ is $12$,
and the length of the path and the length of the path
$1 \rightarrow 3 \rightarrow 4 \rightarrow 5$ is $11$. $1 \rightarrow 3 \rightarrow 4 \rightarrow 5$ is $11$.
The latter path is the \key{shortest} path from node $1$ to node $5$. The latter path is the \key{shortest} path from node $1$ to node $5$.
@ -313,7 +312,7 @@ that end at the node,
and the \key{outdegree} of a node and the \key{outdegree} of a node
is the number of edges that start at the node. is the number of edges that start at the node.
For example, in the following graph, For example, in the following graph,
the indegree of node 2 is 2 the indegree of node 2 is 2,
and the outdegree of node 2 is 1. and the outdegree of node 2 is 1.
\begin{center} \begin{center}
@ -548,7 +547,7 @@ adj[3].push_back({4,5});
adj[4].push_back({1,2}); adj[4].push_back({1,2});
\end{lstlisting} \end{lstlisting}
The benefit in using adjacency lists is that The benefit of using adjacency lists is that
we can efficiently find the nodes to which we can efficiently find the nodes to which
we can move from a given node through an edge. we can move from a given node through an edge.
For example, the following loop goes through all nodes For example, the following loop goes through all nodes
@ -677,7 +676,7 @@ corresponds to the following matrix:
\end{center} \end{center}
\end{samepage} \end{samepage}
The drawback in the adjacency matrix representation The drawback of the adjacency matrix representation
is that there are $n^2$ elements in the matrix is that there are $n^2$ elements in the matrix
and usually most of them are zero. and usually most of them are zero.
For this reason, the representation cannot be used For this reason, the representation cannot be used
@ -753,7 +752,7 @@ For example, the graph
\begin{samepage} \begin{samepage}
can be represented as follows\footnote{In some older compilers, the function can be represented as follows\footnote{In some older compilers, the function
\texttt{make\_tuple} must be used instead of the braces (for example, \texttt{make\_tuple} must be used instead of the braces (for example,
\texttt{make\_tuple(1,2,5)} instead of \texttt{\{1,2,5\}}.}: \texttt{make\_tuple(1,2,5)} instead of \texttt{\{1,2,5\}}).}:
\begin{lstlisting} \begin{lstlisting}
edges.push_back({1,2,5}); edges.push_back({1,2,5});
edges.push_back({2,3,7}); edges.push_back({2,3,7});

View File

@ -19,7 +19,7 @@ is a straightforward graph traversal technique.
The algorithm begins at a starting node, The algorithm begins at a starting node,
and proceeds to all other nodes that are and proceeds to all other nodes that are
reachable from the starting node using reachable from the starting node using
the edges in the graph. the edges of the graph.
Depth-first search always follows a single Depth-first search always follows a single
path in the graph as long as it finds path in the graph as long as it finds
@ -48,8 +48,8 @@ the following graph:
\path[draw,thick,-] (2) -- (5); \path[draw,thick,-] (2) -- (5);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
We may begin the search at any node in the graph, We may begin the search at any node of the graph;
but we will now begin the search at node 1. now we will begin the search at node 1.
The search first proceeds to node 2: The search first proceeds to node 2:
\begin{center} \begin{center}
@ -91,7 +91,7 @@ After this, nodes 3 and 5 will be visited:
\end{center} \end{center}
The neighbors of node 5 are 2 and 3, The neighbors of node 5 are 2 and 3,
but the search has already visited both of them, but the search has already visited both of them,
so it is time to return to previous nodes. so it is time to return to the previous nodes.
Also the neighbors of nodes 3 and 2 Also the neighbors of nodes 3 and 2
have been visited, so we next move have been visited, so we next move
from node 1 to node 4: from node 1 to node 4:
@ -174,7 +174,7 @@ have been visited.
\subsubsection*{Example} \subsubsection*{Example}
Let us consider how the algorithm processes Let us consider how breadth-first search processes
the following graph: the following graph:
\begin{center} \begin{center}
@ -186,7 +186,6 @@ the following graph:
\node[draw, circle] (5) at (3,3) {$5$}; \node[draw, circle] (5) at (3,3) {$5$};
\node[draw, circle] (6) at (5,3) {$6$}; \node[draw, circle] (6) at (5,3) {$6$};
\path[draw,thick,-] (1) -- (2); \path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3); \path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4); \path[draw,thick,-] (1) -- (4);
@ -195,7 +194,7 @@ the following graph:
\path[draw,thick,-] (5) -- (6); \path[draw,thick,-] (5) -- (6);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Suppose again that the search begins at node 1. Suppose that the search begins at node 1.
First, we process all nodes that can be reached First, we process all nodes that can be reached
from node 1 using a single edge: from node 1 using a single edge:
\begin{center} \begin{center}
@ -276,7 +275,7 @@ Finally, we visit node 6:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Now we have calculated the distances Now we have calculated the distances
from the starting node to all nodes in the graph. from the starting node to all nodes of the graph.
The distances are as follows: The distances are as follows:
\begin{tabular}{ll} \begin{tabular}{ll}
@ -294,7 +293,7 @@ node & distance \\
Like in depth-first search, Like in depth-first search,
the time complexity of breadth-first search the time complexity of breadth-first search
is $O(n+m)$ where $n$ is the number of nodes is $O(n+m)$, where $n$ is the number of nodes
and $m$ is the number of edges. and $m$ is the number of edges.
\subsubsection*{Implementation} \subsubsection*{Implementation}
@ -318,15 +317,15 @@ int dist[N];
\end{lstlisting} \end{lstlisting}
The queue \texttt{q} The queue \texttt{q}
contains the nodes in increasing order contains nodes to be processed
of their distance. in increasing order of their distance.
New nodes are always added to the end New nodes are always added to the end
of the queue, and the node at the beginning of the queue, and the node at the beginning
of the queue is the next node to be processed. of the queue is the next node to be processed.
The array \texttt{vis} indicates The array \texttt{vis} indicates
which nodes the search has already visited, which nodes the search has already visited,
and the array \texttt{dist} will contain the and the array \texttt{dist} will contain the
distances to all nodes in the graph. distances from the starting node to all nodes of the graph.
The search can be implemented as follows, The search can be implemented as follows,
starting at node $x$: starting at node $x$:
@ -349,9 +348,9 @@ while (!q.empty()) {
\section{Applications} \section{Applications}
Using the graph traversal algorithms, Using the graph traversal algorithms,
we can check many properties of the graph. we can check many properties of graphs.
Usually, either depth-first search or Usually, both depth-first search and
bredth-first search can be used, bredth-first search may be used,
but in practice, depth-first search but in practice, depth-first search
is a better choice, because it is is a better choice, because it is
easier to implement. easier to implement.
@ -363,9 +362,9 @@ assume that the graph is undirected.
\index{connected graph} \index{connected graph}
A graph is connected if there is a path A graph is connected if there is a path
between any two nodes in the graph. between any two nodes of the graph.
Thus, we can check if a graph is connected Thus, we can check if a graph is connected
by choosing an arbitrary node and by starting at an arbitrary node and
finding out if we can reach all other nodes. finding out if we can reach all other nodes.
For example, in the graph For example, in the graph
@ -459,9 +458,8 @@ of them as follows:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
When we move from After moving from node 2 to node 5 we notice that
node 2 to node 5 it turns out the neighbor 3 of node 5 has already been visited.
that the neighbor 3 has already been visited.
Thus, the graph contains a cycle that goes through node 3, Thus, the graph contains a cycle that goes through node 3,
for example, $3 \rightarrow 2 \rightarrow 5 \rightarrow 3$. for example, $3 \rightarrow 2 \rightarrow 5 \rightarrow 3$.

View File

@ -2,19 +2,19 @@
\index{shortest path} \index{shortest path}
Finding the shortest path between two nodes Finding a shortest path between two nodes
of a graph of a graph
is an important problem that has many is an important problem that has many
applications in practice. practical applications.
For example, a natural problem in a road network For example, a natural problem related to a road network
is to calculate the length of the shortest route is to calculate the shortest possible length of a route
between two cities, given the lengths of the roads. between two cities, given the lengths of the roads.
In an unweighted graph, the length of a path equals In an unweighted graph, the length of a path equals
the number of edges in the path and we can the number of its edges, and we can
simply use breadth-first search to find simply use breadth-first search to find
the shortest path. a shortest path.
However, in this chapter we concentrate on However, in this chapter we focus on
weighted graphs weighted graphs
where more sophisticated algorithms where more sophisticated algorithms
are needed are needed
@ -26,9 +26,9 @@ for finding shortest paths.
The \key{BellmanFord algorithm}\footnote{The algorithm is named after The \key{BellmanFord algorithm}\footnote{The algorithm is named after
R. E. Bellman and L. R. Ford who published it independently R. E. Bellman and L. R. Ford who published it independently
in 1958 and 1956, respectively \cite{bel58,for56a}.} finds the in 1958 and 1956, respectively \cite{bel58,for56a}.} finds
shortest paths from a starting node to all shortest paths from a starting node to all
other nodes in the graph. nodes of the graph.
The algorithm can process all kinds of graphs, The algorithm can process all kinds of graphs,
provided that the graph does not contain a provided that the graph does not contain a
cycle with negative length. cycle with negative length.
@ -36,7 +36,7 @@ If the graph contains a negative cycle,
the algorithm can detect this. the algorithm can detect this.
The algorithm keeps track of distances The algorithm keeps track of distances
from the starting node to other nodes. from the starting node to all nodes of the graph.
Initially, the distance to the starting node is 0 Initially, the distance to the starting node is 0
and the distance to all other nodes in infinite. and the distance to all other nodes in infinite.
The algorithm reduces the distances by finding The algorithm reduces the distances by finding
@ -68,7 +68,7 @@ works in the following graph:
\path[draw,thick,-] (1) -- node[font=\small,label=above:7] {} (4); \path[draw,thick,-] (1) -- node[font=\small,label=above:7] {} (4);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Each node in the graph is assigned a distance. Each node of the graph is assigned a distance.
Initially, the distance to the starting node is 0, Initially, the distance to the starting node is 0,
and the distance to all other nodes is infinite. and the distance to all other nodes is infinite.
@ -152,10 +152,10 @@ Finally, there is one more change:
\end{center} \end{center}
After this, no edge can reduce any distance. After this, no edge can reduce any distance.
This means that the distances are final This means that the distances are final,
and we have successfully and we have successfully
calculated the shortest distance calculated the shortest distances
from the starting node to all other nodes. from the starting node to all nodes of the graph.
For example, the shortest distance 3 For example, the shortest distance 3
from node 1 to node 5 corresponds to from node 1 to node 5 corresponds to
@ -190,8 +190,8 @@ the following path:
\subsubsection{Implementation} \subsubsection{Implementation}
The following implementation of the The following implementation of the
BellmanFord algorithm finds the shortest distances BellmanFord algorithm determines the shortest distances
from a node $x$ to all other nodes in the graph. from a node $x$ to all nodes of the graph.
The code assumes that the graph is stored The code assumes that the graph is stored
as an edge list \texttt{edges} as an edge list \texttt{edges}
that consists of tuples of the form $(a,b,w)$, that consists of tuples of the form $(a,b,w)$,
@ -203,8 +203,8 @@ and on each round the algorithm goes through
all edges of the graph and tries to all edges of the graph and tries to
reduce the distances. reduce the distances.
The algorithm constructs an array \texttt{dist} The algorithm constructs an array \texttt{dist}
that will contain the distance from $x$ that will contain the distances from $x$
to all nodes in the graph. to all nodes of the graph.
The constant \texttt{INF} denotes an infinite distance. The constant \texttt{INF} denotes an infinite distance.
\begin{lstlisting} \begin{lstlisting}
@ -236,7 +236,7 @@ can be reduced during a round.
\index{negative cycle} \index{negative cycle}
The BellmanFord algorithm can be also used to The BellmanFord algorithm can also be used to
check if the graph contains a cycle with negative length. check if the graph contains a cycle with negative length.
For example, the graph For example, the graph
@ -260,8 +260,8 @@ $2 \rightarrow 3 \rightarrow 4 \rightarrow 2$
with length $-4$. with length $-4$.
If the graph contains a negative cycle, If the graph contains a negative cycle,
we can shorten a path that contains the cycle we can shorten infinitely many times
infinitely many times by repeating the cycle any path that contains the cycle by repeating the cycle
again and again. again and again.
Thus, the concept of a shortest path Thus, the concept of a shortest path
is not meaningful in this situation. is not meaningful in this situation.
@ -333,10 +333,10 @@ original BellmanFord algorithm.
\key{Dijkstra's algorithm}\footnote{E. W. Dijkstra published the algorithm in 1959 \cite{dij59}; \key{Dijkstra's algorithm}\footnote{E. W. Dijkstra published the algorithm in 1959 \cite{dij59};
however, his original paper does not mention how to implement the algorithm efficiently.} however, his original paper does not mention how to implement the algorithm efficiently.}
finds the shortest finds shortest
paths from the starting node to all other nodes, paths from the starting node to all nodes of the graph,
like the BellmanFord algorithm. like the BellmanFord algorithm.
The benefit in Dijsktra's algorithm is that The benefit of Dijsktra's algorithm is that
it is more efficient and can be used for it is more efficient and can be used for
processing large graphs. processing large graphs.
However, the algorithm requires that there However, the algorithm requires that there
@ -415,7 +415,8 @@ and reduces the distances using them:
\path[draw=red,thick,->,line width=2pt] (4) -- (5); \path[draw=red,thick,->,line width=2pt] (4) -- (5);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
The edges from node 1 reduced distances to In this case,
the edges from node 1 reduced the distances of
nodes 2, 4 and 5, whose distances are now 5, 9 and 1. nodes 2, 4 and 5, whose distances are now 5, 9 and 1.
The next node to be processed is node 5 with distance 1: The next node to be processed is node 5 with distance 1:
@ -538,7 +539,7 @@ compensates the previous large weight $6$.
The following implementation of Dijkstra's algorithm The following implementation of Dijkstra's algorithm
calculates the minimum distances from a node $x$ calculates the minimum distances from a node $x$
to all other nodes. to other nodes of the graph.
The graph is stored as adjacency lists The graph is stored as adjacency lists
so that \texttt{adj[$a$]} contains a pair $(b,w)$ so that \texttt{adj[$a$]} contains a pair $(b,w)$
always when there is an edge from node $a$ to node $b$ always when there is an edge from node $a$ to node $b$
@ -552,13 +553,14 @@ that contains the nodes ordered by their distances.
Using a priority queue, the next node to be processed Using a priority queue, the next node to be processed
can be retrieved in logarithmic time. can be retrieved in logarithmic time.
The following implementation uses a priority queue In the following code,
\texttt{q} that contains pairs of the form $(-d,x)$: the priority queue
the current distance to node $x$ is $d$. \texttt{q} contains pairs of the form $(-d,x)$,
meaning that the current distance to node $x$ is $d$.
The array $\texttt{dist}$ contains the distance to The array $\texttt{dist}$ contains the distance to
each node, and the array $\texttt{ready}$ indicates each node, and the array $\texttt{ready}$ indicates
whether a node has been processed. whether a node has been processed.
Initially the distance to $0$ to $x$ and $\infty$ to all other nodes. Initially the distance is $0$ to $x$ and $\infty$ to all other nodes.
\begin{lstlisting} \begin{lstlisting}
for (int i = 1; i <= n; i++) dist[i] = INF; for (int i = 1; i <= n; i++) dist[i] = INF;
@ -580,8 +582,9 @@ while (!q.empty()) {
Note that the priority queue contains \emph{negative} Note that the priority queue contains \emph{negative}
distances to nodes. distances to nodes.
The reason for this is that the C++ priority queue finds maximum The reason for this is that the
elements by default while we want to find minimum elements. default version of the C++ priority queue finds maximum
elements, while we want to find minimum elements.
By using negative distances, By using negative distances,
we can directly use the default version of the C++ priority queue\footnote{Of we can directly use the default version of the C++ priority queue\footnote{Of
course, we could also declare the priority queue as in Chapter 4.5 course, we could also declare the priority queue as in Chapter 4.5
@ -591,8 +594,8 @@ node in the priority queue; however, only the instance with the
minimum distance will be processed. minimum distance will be processed.
The time complexity of the above implementation is The time complexity of the above implementation is
$O(n+m \log m)$ because the algorithm goes through $O(n+m \log m)$, because the algorithm goes through
all nodes in the graph and adds for each edge all nodes of the graph and adds for each edge
at most one distance to the priority queue. at most one distance to the priority queue.
\section{FloydWarshall algorithm} \section{FloydWarshall algorithm}
@ -602,9 +605,9 @@ at most one distance to the priority queue.
The \key{FloydWarshall algorithm}\footnote{The algorithm The \key{FloydWarshall algorithm}\footnote{The algorithm
is named after R. W. Floyd and S. Warshall is named after R. W. Floyd and S. Warshall
who published it independently in 1962 \cite{flo62,war62}.} who published it independently in 1962 \cite{flo62,war62}.}
is an alternative way to approach the problem provides an alternative way to approach the problem
of finding shortest paths. of finding shortest paths.
Unlike the other algorithms in this chapter, Unlike the other algorithms of this chapter,
it finds all shortest paths between the nodes it finds all shortest paths between the nodes
in a single run. in a single run.
@ -775,9 +778,7 @@ for (int i = 1; i <= n; i++) {
} }
} }
\end{lstlisting} \end{lstlisting}
After this, the shortest distances can be found as follows: After this, the shortest distances can be found as follows:
\begin{lstlisting} \begin{lstlisting}
for (int k = 1; k <= n; k++) { for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) { for (int i = 1; i <= n; i++) {

View File

@ -79,7 +79,7 @@ and the parent is node 1.
\index{subtree} \index{subtree}
The structure of a rooted tree is \emph{recursive}: The structure of a rooted tree is \emph{recursive}:
each node in the tree is the root of a \key{subtree} each node of the tree acts as the root of a \key{subtree}
that contains the node itself and all other nodes that contains the node itself and all other nodes
that can be reached by traversing down the tree. that can be reached by traversing down the tree.
For example, in the above tree, the subtree of node 4 For example, in the above tree, the subtree of node 4
@ -88,7 +88,7 @@ consists of nodes 4, 3 and 7.
\section{Tree traversal} \section{Tree traversal}
Depth-first search and breadth-first search Depth-first search and breadth-first search
can be used for traversing the nodes in a tree. can be used for traversing the nodes of a tree.
The traversal of a tree is easier to implement than The traversal of a tree is easier to implement than
that of a general graph, because that of a general graph, because
there are no cycles in the tree and it is not there are no cycles in the tree and it is not
@ -129,8 +129,7 @@ to proceed to any direction in the tree.
Dynamic programming can be used to calculate Dynamic programming can be used to calculate
some information during a tree traversal. some information during a tree traversal.
Using dynamic programming, we can, for example, Using dynamic programming, we can, for example,
calculate in $O(n)$ time for each node calculate in $O(n)$ time for each node of a rooted tree the
in a rooted tree the
number of nodes in its subtree number of nodes in its subtree
or the length of the longest path from the node or the length of the longest path from the node
to a leaf. to a leaf.
@ -158,8 +157,8 @@ void dfs(int s, int e) {
\index{diameter} \index{diameter}
The \key{diameter} of a tree The \key{diameter} of a tree
is the length of the longest path is the maximum length of a path
between two nodes in the tree. between two nodes of the tree.
For example, in the tree For example, in the tree
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -194,12 +193,11 @@ to calculate the diameter.
First, we root the tree arbitrarily. First, we root the tree arbitrarily.
After this, we use dynamic programming After this, we use dynamic programming
to calculate for each node $x$ to calculate for each node $x$
the length of the longest path that begins at some leaf, the maximum length of a path that begins at some leaf,
ascends to $x$ and then descends to another leaf. ascends to $x$ and then descends to another leaf.
The length of the The maximum length of such a path equals the diameter of the tree.
longest such path equals the diameter of the tree.
In the example graph, the longest path begins at node 7, In the example graph, a longest path begins at node 7,
ascends to node 1, and then descends to node 6: ascends to node 1, and then descends to node 6:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -225,18 +223,18 @@ ascends to node 1, and then descends to node 6:
\end{center} \end{center}
The algorithm first calculates for each node $x$ The algorithm first calculates for each node $x$
the length of the longest path from $x$ to a leaf. the maximum length of a path from $x$ to a leaf.
For example, in the above tree, For example, in the above tree,
the longest path from node 1 to a leaf has length 2 a longest path from node 1 to a leaf has length 2
(the path can be $1 \rightarrow 4 \rightarrow 3$, (the path can be $1 \rightarrow 4 \rightarrow 3$,
$1 \rightarrow 4 \rightarrow 7$ or $1 \rightarrow 2 \rightarrow 6$). $1 \rightarrow 4 \rightarrow 7$ or $1 \rightarrow 2 \rightarrow 6$).
After this, the algorithm calculates for each node After this, the algorithm calculates for each node
$x$ the length of the longest path where $x$ $x$ the maximum length of a path where $x$
is the highest point of the path. is the highest point of the path.
The longest such path can be found by choosing Such a path can be found by choosing
two children with longest paths to leaves. two children with longest paths to leaves.
For example, in the above graph, For example, in the above graph,
nodes 2 and 4 yield the longest path for node 1. nodes 2 and 4 yield a longest path for node 1.
\subsubsection{Algorithm 2} \subsubsection{Algorithm 2}
@ -319,7 +317,7 @@ a starting node of a path that corresponds to the diameter.
\section{Distances between nodes} \section{Distances between nodes}
A more difficult problem is to calculate A more difficult problem is to calculate
for each node in the tree and for each direction, for each node of the tree and for each direction,
the maximum distance to a node in that direction. the maximum distance to a node in that direction.
It turns out that this can be calculated in It turns out that this can be calculated in
$O(n)$ time using dynamic programming. $O(n)$ time using dynamic programming.
@ -498,7 +496,7 @@ For example, the following tree is a binary tree:
\index{in-order} \index{in-order}
\index{post-order} \index{post-order}
The nodes in a binary tree have three natural The nodes of a binary tree have three natural
orderings that correspond to different ways to orderings that correspond to different ways to
recursively traverse the tree: recursively traverse the tree:

View File

@ -46,7 +46,7 @@ A possible spanning tree for the graph is as follows:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
The weight of a spanning tree is the sum of the edge weights. The weight of a spanning tree is the sum of its edge weights.
For example, the weight of the above spanning tree is For example, the weight of the above spanning tree is
$3+5+9+3+2=22$. $3+5+9+3+2=22$.
@ -103,9 +103,8 @@ example graph is 32:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Note that there may be several Note that a graph may have several
minimum and maximum spanning trees minimum and maximum spanning trees,
for a graph,
so the trees are not unique. so the trees are not unique.
This chapter discusses algorithms This chapter discusses algorithms
@ -166,7 +165,7 @@ following graph:
\end{samepage} \end{samepage}
\begin{samepage} \begin{samepage}
The first step in the algorithm is to sort the The first step of the algorithm is to sort the
edges in increasing order of their weights. edges in increasing order of their weights.
The result is the following list: The result is the following list:
@ -211,7 +210,7 @@ Initially, each node is in its own component:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
The first edge to be added to the tree is The first edge to be added to the tree is
the edge 5--6 that creates the component $\{5,6\}$ the edge 5--6 that creates a component $\{5,6\}$
by joining the components $\{5\}$ and $\{6\}$: by joining the components $\{5\}$ and $\{6\}$:
\begin{center} \begin{center}
@ -301,7 +300,7 @@ Why does the greedy strategy guarantee that we
will find a minimum spanning tree? will find a minimum spanning tree?
Let us see what happens if the minimum weight edge of Let us see what happens if the minimum weight edge of
the graph is not included in the spanning tree. the graph is \emph{not} included in the spanning tree.
For example, suppose that a spanning tree For example, suppose that a spanning tree
for the previous graph would not contain the for the previous graph would not contain the
minimum weight edge 5--6. minimum weight edge 5--6.
@ -362,8 +361,8 @@ always produces a minimum spanning tree.
\subsubsection{Implementation} \subsubsection{Implementation}
When implementing Kruskal's algorithm, When implementing Kruskal's algorithm,
the edge list representation of the graph it is convenient to use
is convenient. the edge list representation of the graph.
The first phase of the algorithm sorts the The first phase of the algorithm sorts the
edges in the list in $O(m \log m)$ time. edges in the list in $O(m \log m)$ time.
After this, the second phase of the algorithm After this, the second phase of the algorithm
@ -380,9 +379,9 @@ and always processes an edge $a$--$b$
where $a$ and $b$ are two nodes. where $a$ and $b$ are two nodes.
Two functions are needed: Two functions are needed:
the function \texttt{same} determines the function \texttt{same} determines
if the nodes are in the same component, if $a$ and $b$ are in the same component,
and the function \texttt{unite} and the function \texttt{unite}
joins the components that contain nodes $a$ and $b$. joins the components that contain $a$ and $b$.
The problem is how to efficiently implement The problem is how to efficiently implement
the functions \texttt{same} and \texttt{unite}. the functions \texttt{same} and \texttt{unite}.
@ -446,7 +445,7 @@ $\{1,4,7\}$, $\{5\}$ and $\{2,3,6,8\}$:
\end{center} \end{center}
In this case the representatives In this case the representatives
of the sets are 4, 5 and 2. of the sets are 4, 5 and 2.
For each element, we can find its representative We can find the representative of any element
by following the chain that begins at the element. by following the chain that begins at the element.
For example, the element 2 is the representative For example, the element 2 is the representative
for the element 6, because for the element 6, because
@ -456,7 +455,7 @@ their representatives are the same.
Two sets can be joined by connecting the Two sets can be joined by connecting the
representative of one set to the representative of one set to the
representative of another set. representative of the other set.
For example, the sets For example, the sets
$\{1,4,7\}$ and $\{2,3,6,8\}$ $\{1,4,7\}$ and $\{2,3,6,8\}$
can be joined as follows: can be joined as follows:
@ -491,7 +490,7 @@ The efficiency of the union-find structure depends on
how the sets are joined. how the sets are joined.
It turns out that we can follow a simple strategy: It turns out that we can follow a simple strategy:
always connect the representative of the always connect the representative of the
smaller set to the representative of the larger set \emph{smaller} set to the representative of the \emph{larger} set
(or if the sets are of equal size, (or if the sets are of equal size,
we can make an arbitrary choice). we can make an arbitrary choice).
Using this strategy, the length of any chain Using this strategy, the length of any chain

View File

@ -20,7 +20,7 @@ on the special properties of the graphs.
\index{topological sorting} \index{topological sorting}
\index{cycle} \index{cycle}
A \key{topological sort} is a ordering A \key{topological sort} is an ordering
of the nodes of a directed graph of the nodes of a directed graph
such that if there is a path from node $a$ to node $b$, such that if there is a path from node $a$ to node $b$,
then node $a$ appears before node $b$ in the ordering. then node $a$ appears before node $b$ in the ordering.
@ -67,8 +67,8 @@ $[4,1,5,2,3,6]$:
An acyclic graph always has a topological sort. An acyclic graph always has a topological sort.
However, if the graph contains a cycle, However, if the graph contains a cycle,
it is not possible to form a topological sort, it is not possible to form a topological sort,
because no node in the cycle can appear because no node of the cycle can appear
before the other nodes in the cycle. before the other nodes of the cycle in the ordering.
It turns out that depth-first search can be used It turns out that depth-first search can be used
to both check if a directed graph contains a cycle to both check if a directed graph contains a cycle
and, if it does not contain a cycle, to construct a topological sort. and, if it does not contain a cycle, to construct a topological sort.
@ -92,7 +92,7 @@ its state becomes 1.
Finally, after all successors of the node have Finally, after all successors of the node have
been processed, its state becomes 2. been processed, its state becomes 2.
If the graph contains a cycle, we will find out this If the graph contains a cycle, we will find this out
during the search, because sooner or later during the search, because sooner or later
we will arrive at a node whose state is 1. we will arrive at a node whose state is 1.
In this case, it is not possible to construct a topological sort. In this case, it is not possible to construct a topological sort.
@ -200,7 +200,7 @@ $[4,5,1,2,3,6]$:
\end{center} \end{center}
Note that a topological sort is not unique, Note that a topological sort is not unique,
but there can be several topological sorts for a graph. and there can be several topological sorts for a graph.
\subsubsection{Example 2} \subsubsection{Example 2}
@ -248,7 +248,8 @@ The search proceeds as follows:
\end{center} \end{center}
The search reaches node 2 whose state is 1, The search reaches node 2 whose state is 1,
which means the graph contains a cycle. which means the graph contains a cycle.
In this example, the cycle is $2 \rightarrow 3 \rightarrow 5 \rightarrow 2$. In this example, there is a cycle
$2 \rightarrow 3 \rightarrow 5 \rightarrow 2$.
\section{Dynamic programming} \section{Dynamic programming}
@ -268,7 +269,7 @@ to an ending node:
\subsubsection{Counting the number of paths} \subsubsection{Counting the number of paths}
As an example, let us calculate the number of paths As an example, let us calculate the number of paths
from node 4 to node 6 in the following graph: from node 1 to node 6 in the following graph:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -281,25 +282,30 @@ from node 4 to node 6 in the following graph:
\path[draw,thick,->,>=latex] (1) -- (2); \path[draw,thick,->,>=latex] (1) -- (2);
\path[draw,thick,->,>=latex] (2) -- (3); \path[draw,thick,->,>=latex] (2) -- (3);
\path[draw,thick,->,>=latex] (4) -- (1); \path[draw,thick,->,>=latex] (1) -- (4);
\path[draw,thick,->,>=latex] (4) -- (5); \path[draw,thick,->,>=latex] (4) -- (5);
\path[draw,thick,->,>=latex] (5) -- (2); \path[draw,thick,->,>=latex] (5) -- (2);
\path[draw,thick,->,>=latex] (5) -- (3); \path[draw,thick,->,>=latex] (5) -- (3);
\path[draw,thick,->,>=latex] (3) -- (6); \path[draw,thick,->,>=latex] (3) -- (6);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
There are a total of three such paths: There are a total of three such paths:
\begin{itemize} \begin{itemize}
\item $4 \rightarrow 1 \rightarrow 2 \rightarrow 3 \rightarrow 6$ \item $1 \rightarrow 2 \rightarrow 3 \rightarrow 6$
\item $4 \rightarrow 5 \rightarrow 2 \rightarrow 3 \rightarrow 6$ \item $1 \rightarrow 4 \rightarrow 5 \rightarrow 2 \rightarrow 3 \rightarrow 6$
\item $4 \rightarrow 5 \rightarrow 3 \rightarrow 6$ \item $1 \rightarrow 4 \rightarrow 5 \rightarrow 3 \rightarrow 6$
\end{itemize} \end{itemize}
To count the paths, Let $p(x)$ denote the number of paths from
we go through the nodes in a topological sort, node 1 to node $x$.
and calculate for each node $x$ the number of paths As a base case, $p(1)=1$.
from node 4 to node $x$. Then, to calculate other values of $p(x)$,
we may use the recursion
\[p(x) = p(a_1)+p(a_2)+\cdots+p(a_k)\]
where $a_1,a_2,\ldots,a_k$ are the nodes from which there
is an edge to $x$.
Since the graph is acyclic, the values of $p(x)$
can be calculated in the order of a topological sort.
A topological sort for the above graph is as follows: A topological sort for the above graph is as follows:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -319,7 +325,6 @@ A topological sort for the above graph is as follows:
\path[draw,thick,->,>=latex] (3) -- (6); \path[draw,thick,->,>=latex] (3) -- (6);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Hence, the numbers of paths are as follows: Hence, the numbers of paths are as follows:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -332,7 +337,7 @@ Hence, the numbers of paths are as follows:
\path[draw,thick,->,>=latex] (1) -- (2); \path[draw,thick,->,>=latex] (1) -- (2);
\path[draw,thick,->,>=latex] (2) -- (3); \path[draw,thick,->,>=latex] (2) -- (3);
\path[draw,thick,->,>=latex] (4) -- (1); \path[draw,thick,->,>=latex] (1) -- (4);
\path[draw,thick,->,>=latex] (4) -- (5); \path[draw,thick,->,>=latex] (4) -- (5);
\path[draw,thick,->,>=latex] (5) -- (2); \path[draw,thick,->,>=latex] (5) -- (2);
\path[draw,thick,->,>=latex] (5) -- (3); \path[draw,thick,->,>=latex] (5) -- (3);
@ -347,18 +352,18 @@ Hence, the numbers of paths are as follows:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
For example, since there are two paths For example, to calculate the value of $p(3)$,
from node 4 to node 2 and we may use the formula $p(2)+p(5)$,
there is one path from node 4 to node 5, because there are edges from nodes 2 and 5
we can conclude that there are three to node 3.
paths from node 4 to node 3. Since $p(2)=2$ and $p(5)=1$, we conclude that $p(3)=3$.
\subsubsection{Extending Dijkstra's algorithm} \subsubsection{Extending Dijkstra's algorithm}
\index{Dijkstra's algorithm} \index{Dijkstra's algorithm}
A by-product of Dijkstra's algorithm is a directed, acyclic A by-product of Dijkstra's algorithm is a directed, acyclic
graph that indicates for each node in the original graph graph that indicates for each node of the original graph
the possible ways to reach the node using a shortest path the possible ways to reach the node using a shortest path
from the starting node. from the starting node.
Dynamic programming can be applied to that graph. Dynamic programming can be applied to that graph.
@ -470,7 +475,7 @@ the graph is as follows:
Using this representation, Using this representation,
the shortest path from node 0 to node $x$ the shortest path from node 0 to node $x$
corresponds to a solution with minimum number of coins, corresponds to a solution with the minimum number of coins,
and the total number of paths from node 0 to node $x$ and the total number of paths from node 0 to node $x$
equals the total number of solutions. equals the total number of solutions.
@ -480,8 +485,9 @@ equals the total number of solutions.
\index{functional graph} \index{functional graph}
For the rest of the chapter, For the rest of the chapter,
we will concentrate on \key{successor graphs} we will focus on \key{successor graphs}.
where the outdegree of each node is 1, i.e., In those graphs,
the outdegree of each node is 1, i.e.,
exactly one edge starts at each node. exactly one edge starts at each node.
A successor graph consists of one or more A successor graph consists of one or more
components, each of which contains components, each of which contains
@ -491,11 +497,10 @@ Successor graphs are sometimes called
\key{functional graphs}. \key{functional graphs}.
The reason for this is that any successor graph The reason for this is that any successor graph
corresponds to a function $f$ that defines corresponds to a function $f$ that defines
the edges in the graph. the edges of the graph.
The parameter for the function is a node in the graph, The parameter for the function is a node of the graph,
and the function gives the successor of the node. and the function gives the successor of that node.
\begin{samepage}
For example, the function For example, the function
\begin{center} \begin{center}
\begin{tabular}{r|rrrrrrrrr} \begin{tabular}{r|rrrrrrrrr}
@ -504,7 +509,6 @@ $x$ & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 \\
$f(x)$ & 3 & 5 & 7 & 6 & 2 & 2 & 1 & 6 & 3 \\ $f(x)$ & 3 & 5 & 7 & 6 & 2 & 2 & 1 & 6 & 3 \\
\end{tabular} \end{tabular}
\end{center} \end{center}
\end{samepage}
defines the following graph: defines the following graph:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -530,8 +534,8 @@ defines the following graph:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Since each node in a successor graph has a Since each node of a successor graph has a
unique successor, we can define a function $f(x,k)$ unique successor, we can also define a function $f(x,k)$
that gives the node that we will reach if that gives the node that we will reach if
we begin at node $x$ and walk $k$ steps forward. we begin at node $x$ and walk $k$ steps forward.
For example, in the above graph $f(4,6)=2$, For example, in the above graph $f(4,6)=2$,
@ -574,7 +578,7 @@ we can use the following recursion:
\end{cases} \end{cases}
\end{equation*} \end{equation*}
Precalculating values $f(x,k)$ takes $O(n \log u)$ time, Precalculating the values takes $O(n \log u)$ time,
because $O(\log u)$ values are calculated for each node. because $O(\log u)$ values are calculated for each node.
In the above graph, the first values are as follows: In the above graph, the first values are as follows:
@ -610,7 +614,7 @@ takes $O(\log k)$ time.
Consider a successor graph that only contains Consider a successor graph that only contains
a path that ends in a cycle. a path that ends in a cycle.
There are two interesting questions: We may ask the following questions:
if we begin our walk at the starting node, if we begin our walk at the starting node,
what is the first node in the cycle what is the first node in the cycle
and how many nodes does the cycle contain? and how many nodes does the cycle contain?

View File

@ -516,8 +516,8 @@ their values will be determined
according to the values in the component, according to the values in the component,
and if they already have values, and if they already have values,
they remain unchanged. they remain unchanged.
The process continues until all variables The process continues until each variable
have been assigned values. has been assigned a value.
The component graph for the formula $L_1$ is as follows: The component graph for the formula $L_1$ is as follows:
\begin{center} \begin{center}

View File

@ -52,16 +52,15 @@ and $f(5,2)=0$.
An easy way to calculate the value of $f(x,k)$ An easy way to calculate the value of $f(x,k)$
is to perform a sequence of $k$ moves in the tree. is to perform a sequence of $k$ moves in the tree.
However, the time complexity of this method However, the time complexity of this method
is $O(n)$, because the tree may contain is $O(k)$, which may be slow, because a tree of $n$
a chain of $O(n)$ nodes. nodes may have a chain of $n$ nodes.
Fortunately, it turns out that Fortunately, using a technique similar to that
using a technique similar to that
used in Chapter 16.3, any value of $f(x,k)$ used in Chapter 16.3, any value of $f(x,k)$
can be efficiently calculated in $O(\log k)$ time can be efficiently calculated in $O(\log k)$ time
after preprocessing. after preprocessing.
The idea is to precalculate all values $f(x,k)$ The idea is to precalculate all values $f(x,k)$
where $k$ is a power of two. where $k \le n$ is a power of two.
For example, the values for the above tree For example, the values for the above tree
are as follows: are as follows:
@ -77,7 +76,7 @@ $\cdots$ \\
\end{center} \end{center}
The preprocessing takes $O(n \log n)$ time, The preprocessing takes $O(n \log n)$ time,
because each node can have at most $n$ ancestors. because $O(\log n)$ values are calculated for each node.
After this, any value of $f(x,k)$ can be calculated After this, any value of $f(x,k)$ can be calculated
in $O(\log k)$ time by representing $k$ in $O(\log k)$ time by representing $k$
as a sum where each term is a power of two. as a sum where each term is a power of two.
@ -185,10 +184,10 @@ Hence, the corresponding tree traversal array is as follows:
\subsubsection{Subtree queries} \subsubsection{Subtree queries}
Each subtree of a tree corresponds to a subarray Each subtree of a tree corresponds to a subarray
in the tree traversal array such that of the tree traversal array such that
the first element in the subarray is the root node. the first element of the subarray is the root node.
For example, the following subarray contains the For example, the following subarray contains the
nodes in the subtree of node $4$: nodes of the subtree of node $4$:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.7] \begin{tikzpicture}[scale=0.7]
\fill[color=lightgray] (4,0) rectangle (8,1); \fill[color=lightgray] (4,0) rectangle (8,1);
@ -382,7 +381,7 @@ can be found as follows:
To answer the queries efficiently, To answer the queries efficiently,
it suffices to store the values of the it suffices to store the values of the
nodes in a binary indexed tree or segment tree. nodes in a binary indexed or segment tree.
After this, we can both update a value After this, we can both update a value
and calculate the sum of values in $O(\log n)$ time. and calculate the sum of values in $O(\log n)$ time.
@ -390,9 +389,9 @@ and calculate the sum of values in $O(\log n)$ time.
Using a tree traversal array, we can also efficiently Using a tree traversal array, we can also efficiently
calculate sums of values on calculate sums of values on
paths from the root node to any other paths from the root node to any
node in the tree. node of the tree.
Let us next consider a problem where our task Let us consider a problem where our task
is to support the following queries: is to support the following queries:
\begin{itemize} \begin{itemize}
\item change the value of a node \item change the value of a node
@ -553,7 +552,7 @@ Thus, to support both the operations,
we should be able to increase all values we should be able to increase all values
in a range and retrieve a single value. in a range and retrieve a single value.
This can be done in $O(\log n)$ time This can be done in $O(\log n)$ time
using a binary indexed tree using a binary indexed
or segment tree (see Chapter 9.4). or segment tree (see Chapter 9.4).
\section{Lowest common ancestor} \section{Lowest common ancestor}
@ -561,11 +560,11 @@ or segment tree (see Chapter 9.4).
\index{lowest common ancestor} \index{lowest common ancestor}
The \key{lowest common ancestor} The \key{lowest common ancestor}
of two nodes in the tree is the lowest node of two nodes of a rooted tree is the lowest node
whose subtree contains both the nodes. whose subtree contains both the nodes.
A typical problem is to efficiently process A typical problem is to efficiently process
queries that ask to find the lowest queries that ask to find the lowest
common ancestor of given two nodes. common ancestor of two nodes.
For example, in the following tree, For example, in the following tree,
the lowest common ancestor of nodes 5 and 8 the lowest common ancestor of nodes 5 and 8
@ -605,13 +604,13 @@ Using this, we can divide the problem of
finding the lowest common ancestor into two parts. finding the lowest common ancestor into two parts.
We use two pointers that initially point to the We use two pointers that initially point to the
two nodes for which we should find the two nodes whose lowest common ancestor we should find.
lowest common ancestor.
First, we move one of the pointers upwards First, we move one of the pointers upwards
so that both nodes are at the same level in the tree. so that both pointers point to nodes at the same level.
In the example case, we move from node 8 to node 6, In the example case, we move the second pointer one
after which both nodes are at the same level: level up so that it points to node 6
which is at the same level with node 5:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -638,7 +637,8 @@ after which both nodes are at the same level:
After this, we determine the minimum number of steps After this, we determine the minimum number of steps
needed to move both pointers upwards so that needed to move both pointers upwards so that
they will point to the same node. they will point to the same node.
This node is the lowest common ancestor of the nodes. The node to which the pointers point after this
is the lowest common ancestor.
In the example case, it suffices to move both pointers In the example case, it suffices to move both pointers
one step upwards to node 2, one step upwards to node 2,
@ -670,12 +670,12 @@ which is the lowest common ancestor:
Since both parts of the algorithm can be performed in Since both parts of the algorithm can be performed in
$O(\log n)$ time using precomputed information, $O(\log n)$ time using precomputed information,
we can find the lowest common ancestor of any two we can find the lowest common ancestor of any two
nodes in $O(\log n)$ time using this technique. nodes in $O(\log n)$ time.
\subsubsection{Method 2} \subsubsection{Method 2}
Another way to solve the problem is based on Another way to solve the problem is based on
a tree traversal array\footnote{This lowest common ancestor algorithm is based on \cite{ben00}. a tree traversal array\footnote{This lowest common ancestor algorithm was presented in \cite{ben00}.
This technique is sometimes called the \index{Euler tour technique} This technique is sometimes called the \index{Euler tour technique}
\key{Euler tour technique} \cite{tar84}.}. \key{Euler tour technique} \cite{tar84}.}.
Once again, the idea is to traverse the nodes Once again, the idea is to traverse the nodes
@ -716,7 +716,7 @@ using a depth-first search:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
However, we use a bit different tree However, we use a different tree
traversal array than before: traversal array than before:
we add each node to the array \emph{always} we add each node to the array \emph{always}
when the depth-first search walks through the node, when the depth-first search walks through the node,
@ -792,8 +792,8 @@ The following array corresponds to the above tree:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Using this array, we can find the lowest common ancestor Now we can find the lowest common ancestor
of nodes $a$ and $b$ by finding the node with lowest level of nodes $a$ and $b$ by finding the node with the \emph{lowest} level
between nodes $a$ and $b$ in the array. between nodes $a$ and $b$ in the array.
For example, the lowest common ancestor of nodes $5$ and $8$ For example, the lowest common ancestor of nodes $5$ and $8$
can be found as follows: can be found as follows:
@ -881,8 +881,8 @@ after an $O(n \log n)$ time preprocessing.
\subsubsection{Distances of nodes} \subsubsection{Distances of nodes}
Finally, let us consider the problem of Finally, let us consider the problem of
finding the distance between calculating the distance between
two nodes in the tree, which equals two nodes of a tree, which equals
the length of the path between them. the length of the path between them.
It turns out that this problem reduces to It turns out that this problem reduces to
finding the lowest common ancestor of the nodes. finding the lowest common ancestor of the nodes.
@ -892,7 +892,7 @@ After this, the distance between nodes $a$ and $b$
can be calculated using the formula can be calculated using the formula
\[d(a)+d(b)-2 \cdot d(c),\] \[d(a)+d(b)-2 \cdot d(c),\]
where $c$ is the lowest common ancestor of $a$ and $b$ where $c$ is the lowest common ancestor of $a$ and $b$
and $d(s)$ denotes the distance from the root node and $d(s)$ denotes the distance from the root
to node $s$. to node $s$.
For example, in the tree For example, in the tree
@ -1149,11 +1149,11 @@ algorithms discussed earlier in this chapter.
The algorithm is given as input a set of pairs of nodes, The algorithm is given as input a set of pairs of nodes,
and it determines for each such pair the and it determines for each such pair the
lowest common ancestor. lowest common ancestor of the nodes.
The algorithm performs a depth-first tree traversal The algorithm performs a depth-first tree traversal
and maintains disjoint sets of nodes. and maintains disjoint sets of nodes.
Initially, each node belongs to a separate set. Initially, each node belongs to a separate set.
For each set, we also maintain the highest node in the For each set, we also store the highest node in the
tree that belongs to the set. tree that belongs to the set.
When the algorithm visits a node $x$, When the algorithm visits a node $x$,
@ -1164,11 +1164,11 @@ If $y$ has already been visited,
the algorithm reports that the the algorithm reports that the
lowest common ancestor of $x$ and $y$ lowest common ancestor of $x$ and $y$
is the highest node in the set of $y$. is the highest node in the set of $y$.
Then, after processing the subtree of $x$, Then, after processing node $x$,
the algorithm combines the sets of $x$ and its parent. the algorithm joins the sets of $x$ and its parent.
For example, assume that we would like the lowest For example, assume that we wish to find the lowest
common ancestor of node pairs $(5,8)$ common ancestors of node pairs $(5,8)$
and $(2,7)$ in the following tree: and $(2,7)$ in the following tree:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.85] \begin{tikzpicture}[scale=0.85]

View File

@ -7,16 +7,17 @@ goes through each edge exactly once.
\item A \key{Hamiltonian path} is a path \item A \key{Hamiltonian path} is a path
that visits each node exactly once. that visits each node exactly once.
\end{itemize} \end{itemize}
While Eulerian and Hamiltonian paths look like While Eulerian and Hamiltonian paths look like
similar concepts at first glance, similar concepts at first glance,
the computational problems related to them the computational problems related to them
are very different. are very different.
It turns out that there is a simple rule that It turns out that there is a simple rule that
determines whether a graph contains an Eulerian path determines whether a graph contains an Eulerian path,
and there is also an efficient algorithm to and there is also an efficient algorithm to
find such a path if it exists. find such a path if it exists.
On the contrary, checking the existence of a Hamiltonian path is a NP-hard On the contrary, checking the existence of a Hamiltonian path is a NP-hard
problem and no efficient algorithm is known for solving the problem. problem, and no efficient algorithm is known for solving the problem.
\section{Eulerian paths} \section{Eulerian paths}
@ -25,7 +26,7 @@ problem and no efficient algorithm is known for solving the problem.
An \key{Eulerian path}\footnote{L. Euler studied such paths in 1736 An \key{Eulerian path}\footnote{L. Euler studied such paths in 1736
when he solved the famous Königsberg bridge problem. when he solved the famous Königsberg bridge problem.
This was the birth of graph theory.} is a path This was the birth of graph theory.} is a path
that goes exactly once through each edge in the graph. that goes exactly once through each edge of the graph.
For example, the graph For example, the graph
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -116,7 +117,7 @@ has an Eulerian circuit that starts and ends at node 1:
\subsubsection{Existence} \subsubsection{Existence}
The existence of Eulerian paths and circuits The existence of Eulerian paths and circuits
depends on the degrees of the nodes in the graph. depends on the degrees of the nodes of the graph.
First, an undirected graph has an Eulerian path if all the edges First, an undirected graph has an Eulerian path if all the edges
belong to the same connected component and belong to the same connected component and
\begin{itemize} \begin{itemize}
@ -125,7 +126,7 @@ belong to the same connected component and
and the degree of all other nodes is even. and the degree of all other nodes is even.
\end{itemize} \end{itemize}
In the first case, each Eulerian path in the graph In the first case, each Eulerian path of the graph
is also an Eulerian circuit. is also an Eulerian circuit.
In the second case, the odd-degree nodes are the starting In the second case, the odd-degree nodes are the starting
and ending nodes of an Eulerian path which is not an Eulerian circuit. and ending nodes of an Eulerian path which is not an Eulerian circuit.
@ -165,10 +166,10 @@ connected component and
\item in each node, the indegree equals the outdegree, \emph{or} \item in each node, the indegree equals the outdegree, \emph{or}
\item in one node, the indegree is one larger than the outdegree, \item in one node, the indegree is one larger than the outdegree,
in another node, the outdegree is one larger than the indegree, in another node, the outdegree is one larger than the indegree,
and all other nodes, the indegree equals the outdegree. and in all other nodes, the indegree equals the outdegree.
\end{itemize} \end{itemize}
In the first case, each Eulerian path in the graph In the first case, each Eulerian path of the graph
is also an Eulerian circuit, is also an Eulerian circuit,
and in the second case, the graph contains an Eulerian path and in the second case, the graph contains an Eulerian path
that begins at the node whose outdegree is larger that begins at the node whose outdegree is larger
@ -235,7 +236,7 @@ an Eulerian circuit; otherwise Hierholzer's
algorithm cannot find it. algorithm cannot find it.
First, the algorithm constructs a circuit that contains First, the algorithm constructs a circuit that contains
some (not necessarily all) of the edges in the graph. some (not necessarily all) of the edges of the graph.
After this, the algorithm extends the circuit After this, the algorithm extends the circuit
step by step by adding subcircuits to it. step by step by adding subcircuits to it.
The process continues until all edges have been added The process continues until all edges have been added
@ -260,7 +261,7 @@ we add the extra edge between the two
odd-degree nodes. odd-degree nodes.
Next we will see how Hierholzer's algorithm Next we will see how Hierholzer's algorithm
constructs an Eulerian circuit in an undirected graph. constructs an Eulerian circuit for an undirected graph.
\subsubsection{Example} \subsubsection{Example}
@ -401,7 +402,7 @@ so we have successfully constructed an Eulerian circuit.
A \key{Hamiltonian path} A \key{Hamiltonian path}
%\footnote{W. R. Hamilton (1805--1865) was an Irish mathematician.} %\footnote{W. R. Hamilton (1805--1865) was an Irish mathematician.}
is a path is a path
that visits each node in the graph exactly once. that visits each node of the graph exactly once.
For example, the graph For example, the graph
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -474,9 +475,9 @@ that begins and ends at node 1:
\subsubsection{Existence} \subsubsection{Existence}
No efficient method is known for testing if a graph No efficient method is known for testing if a graph
contains a Hamiltonian path, but the problem is NP-hard. contains a Hamiltonian path, and the problem is NP-hard.
Still, in some special cases we can be certain Still, in some special cases, we can be certain
that the graph contains a Hamiltonian path. that a graph contains a Hamiltonian path.
A simple observation is that if the graph is complete, A simple observation is that if the graph is complete,
i.e., there is an edge between all pairs of nodes, i.e., there is an edge between all pairs of nodes,
@ -507,7 +508,7 @@ the more possibilities there is to construct a Hamiltonian path.
Since there is no efficient way to check if a Hamiltonian Since there is no efficient way to check if a Hamiltonian
path exists, it is clear that there is also no method path exists, it is clear that there is also no method
for constructing the path efficiently, because otherwise to efficiently construct the path, because otherwise
we could just try to construct the path and see we could just try to construct the path and see
whether it exists. whether it exists.
@ -523,7 +524,7 @@ The idea is to define a function $f(s,x)$,
where $s$ is a subset of nodes and $x$ where $s$ is a subset of nodes and $x$
is one of the nodes in the subset. is one of the nodes in the subset.
The function indicates whether there is a Hamiltonian path The function indicates whether there is a Hamiltonian path
that visits the nodes in $s$ and ends at node $x$. that visits the nodes of $s$ and ends at node $x$.
It is possible to implement this solution in $O(2^n n^2)$ time. It is possible to implement this solution in $O(2^n n^2)$ time.
\section{De Bruijn sequences} \section{De Bruijn sequences}
@ -547,8 +548,8 @@ combinations of three bits:
It turns out that each De Bruijn sequence It turns out that each De Bruijn sequence
corresponds to an Eulerian path in a graph. corresponds to an Eulerian path in a graph.
The idea is to construct the graph so that The idea is to construct the graph where
each node contains a combination of $n-1$ characters each node contains a string of $n-1$ characters
and each edge adds one character to the string. and each edge adds one character to the string.
The following graph corresponds to the above example: The following graph corresponds to the above example:
@ -575,7 +576,7 @@ The following graph corresponds to the above example:
An Eulerian path in this graph corresponds to a string An Eulerian path in this graph corresponds to a string
that contains all strings of length $n$. that contains all strings of length $n$.
The string contains the characters of the starting node The string contains the characters of the starting node
and all characters in the edges. and all characters of the edges.
The starting node has $n-1$ characters The starting node has $n-1$ characters
and there are $k^n$ characters in the edges, and there are $k^n$ characters in the edges,
so the length of the string is $k^n+n-1$. so the length of the string is $k^n+n-1$.
@ -588,9 +589,9 @@ A \key{knight's tour} is a sequence of moves
of a knight on an $n \times n$ chessboard of a knight on an $n \times n$ chessboard
following the rules of chess such that the knight following the rules of chess such that the knight
visits each square exactly once. visits each square exactly once.
A tour is \emph{closed} if the knight finally A knight's tour is called a \emph{closed} tour
returns to the starting square and if the knight finally returns to the starting square and
otherwise it is \emph{open}. otherwise it is called an \emph{open} tour.
For example, here is an open knight's tour on a $5 \times 5$ board: For example, here is an open knight's tour on a $5 \times 5$ board:
@ -626,13 +627,13 @@ For example, here is an open knight's tour on a $5 \times 5$ board:
\end{center} \end{center}
A knight's tour corresponds to a Hamiltonian path in a graph A knight's tour corresponds to a Hamiltonian path in a graph
whose nodes represent the squares of the board whose nodes represent the squares of the board,
and two nodes are connected with an edge if a knight and two nodes are connected with an edge if a knight
can move between the squares according to the rules of chess. can move between the squares according to the rules of chess.
A natural way to construct a knight's tour is to use backtracking. A natural way to construct a knight's tour is to use backtracking.
The search can be made more efficient by using The search can be made more efficient by using
\key{heuristics} that attempt to guide the knight so that \emph{heuristics} that attempt to guide the knight so that
a complete tour will be found quickly. a complete tour will be found quickly.
\subsubsection{Warnsdorf's rule} \subsubsection{Warnsdorf's rule}
@ -651,7 +652,7 @@ The idea is to always move the knight so that it ends up
in a square where the number of possible moves is as in a square where the number of possible moves is as
\emph{small} as possible. \emph{small} as possible.
For example, in the following situation there are five For example, in the following situation, there are five
possible squares to which the knight can move: possible squares to which the knight can move:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.7] \begin{tikzpicture}[scale=0.7]

View File

@ -1,6 +1,6 @@
\chapter{Flows and cuts} \chapter{Flows and cuts}
In this chapter, we will focus on the following In this chapter, we focus on the following
two problems: two problems:
\begin{itemize} \begin{itemize}
@ -14,8 +14,8 @@ that separates two nodes of the graph?
The input for both these problems is a directed, The input for both these problems is a directed,
weighted graph that contains two special nodes: weighted graph that contains two special nodes:
the \key{source} is a node with no incoming edges, the \emph{source} is a node with no incoming edges,
and the \key{sink} is a node with no outgoing edges. and the \emph{sink} is a node with no outgoing edges.
As an example, we will use the following graph As an example, we will use the following graph
where node 1 is the source and node 6 where node 1 is the source and node 6
@ -55,7 +55,7 @@ In each intermediate node,
the incoming and outgoing the incoming and outgoing
flow has to be equal. flow has to be equal.
For example, the size of the maximum flow For example, the maximum size of a flow
in the example graph is 7. in the example graph is 7.
The following picture shows how we can The following picture shows how we can
route the flow: route the flow:
@ -102,7 +102,7 @@ to the sink after the removal
and the total weight of the removed edges and the total weight of the removed edges
is minimum. is minimum.
The size of the minimum cut in the example graph is 7. The minimum size of a cut in the example graph is 7.
It suffices to remove the edges $2 \rightarrow 3$ It suffices to remove the edges $2 \rightarrow 3$
and $4 \rightarrow 5$: and $4 \rightarrow 5$:
@ -140,11 +140,12 @@ way to remove edges from the graph such that
their total weight would be less than $7$. their total weight would be less than $7$.
\\\\ \\\\
It is not a coincidence that It is not a coincidence that
both the size of the maximum flow and the maximum size of a flow
the size of the minimum cut is 7 in the above example. and the minimum size of a cut
It turns out that the size of the maximum flow are the same in the above example.
and the minimum cut is It turns out that a maximum flow
\emph{always} the same, and a minimum cut are
\emph{always} equally large,
so the concepts are two sides of the same coin. so the concepts are two sides of the same coin.
Next we will discuss the FordFulkerson Next we will discuss the FordFulkerson
@ -160,10 +161,10 @@ The algorithm also helps us to understand
The \key{FordFulkerson algorithm} \cite{for56} finds The \key{FordFulkerson algorithm} \cite{for56} finds
the maximum flow in a graph. the maximum flow in a graph.
The algorithm begins with an empty flow, The algorithm begins with an empty flow,
and at each step finds a path in the graph and at each step finds a path from the source
that generates more flow. to the sink that generates more flow.
Finally, when the algorithm cannot increase the flow Finally, when the algorithm cannot increase the flow
anymore, it terminates and the maximum flow has been found. anymore, the maximum flow has been found.
The algorithm uses a special representation The algorithm uses a special representation
of the graph where each original edge has a reverse of the graph where each original edge has a reverse
@ -293,7 +294,7 @@ and the new graph is as follows:
The idea is that increasing the flow decreases the amount of The idea is that increasing the flow decreases the amount of
flow that can go through the edges in the future. flow that can go through the edges in the future.
On the other hand, it is possible to modify the On the other hand, it is possible to cancel
flow later using the reverse edges of the graph flow later using the reverse edges of the graph
if it turns out that if it turns out that
it would be beneficial to route the flow in another way. it would be beneficial to route the flow in another way.
@ -435,7 +436,7 @@ chooses each path so that the number of edges
on the path is as small as possible. on the path is as small as possible.
This can be done by using breadth-first search This can be done by using breadth-first search
instead of depth-first search for finding paths. instead of depth-first search for finding paths.
It turns out that this guarantees that It can be proven that this guarantees that
the flow increases quickly, and the time complexity the flow increases quickly, and the time complexity
of the algorithm is $O(m^2 n)$. of the algorithm is $O(m^2 n)$.
@ -445,8 +446,8 @@ The \key{scaling algorithm} \cite{ahu91} uses depth-first
search to find paths where each edge weight is search to find paths where each edge weight is
at least a threshold value. at least a threshold value.
Initially, the threshold value is Initially, the threshold value is
the sum of capacities of the edges that some large number, for example the sum of all
start at the source. edge weights of the graph.
Always when a path cannot be found, Always when a path cannot be found,
the threshold value is divided by 2. the threshold value is divided by 2.
The time complexity of the algorithm is $O(m^2 \log c)$, The time complexity of the algorithm is $O(m^2 \log c)$,
@ -463,7 +464,7 @@ that typically appear in programming contests.
It turns out that once the FordFulkerson algorithm It turns out that once the FordFulkerson algorithm
has found a maximum flow, has found a maximum flow,
it has also found a minimum cut. it has also determined a minimum cut.
Let $A$ be the set of nodes Let $A$ be the set of nodes
that can be reached from the source that can be reached from the source
using positive-weight edges. using positive-weight edges.
@ -509,14 +510,14 @@ Why is the flow produced by the algorithm maximum
and why is the cut minimum? and why is the cut minimum?
The reason is that a graph cannot The reason is that a graph cannot
contain a flow whose size is larger contain a flow whose size is larger
than the weight of any cut in the graph. than the weight of any cut of the graph.
Hence, always when a flow and a cut are equally large, Hence, always when a flow and a cut are equally large,
they are a maximum flow and a minimum cut. they are a maximum flow and a minimum cut.
Let us consider any cut in the graph Let us consider any cut of the graph
such that the source belongs to $A$, such that the source belongs to $A$,
the sink belongs to $B$ the sink belongs to $B$
and there are edges between the sets: and there are some edges between the sets:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -645,8 +646,8 @@ to the sink.
In this problem, every node, In this problem, every node,
except for the source and sink, except for the source and sink,
may appear in at most one path. may appear in at most one path.
The number of node-disjoint paths is The number of node-disjoint paths
often smaller than the number of may be smaller than the number of
edge-disjoint paths. edge-disjoint paths.
For example, in the previous graph, For example, in the previous graph,
@ -682,9 +683,9 @@ Since each node can appear in at most one path,
we have to limit the flow that goes through the nodes. we have to limit the flow that goes through the nodes.
A standard method for this is to divide each node into A standard method for this is to divide each node into
two nodes such that the first node has the incoming edges two nodes such that the first node has the incoming edges
of the original node and the second node has the outgoing of the original node, the second node has the outgoing
edges of the original node. edges of the original node, and
In addition, there is a new edge from the first node there is a new edge from the first node
to the second node. to the second node.
In our example, the graph becomes as follows: In our example, the graph becomes as follows:
@ -772,7 +773,7 @@ from the source to the sink is 1.
\index{maximum matching} \index{maximum matching}
The \key{maximum matching} problem asks to find The \key{maximum matching} problem asks to find
a maximum-size set of node pairs in a graph a maximum-size set of node pairs of a graph
such that each pair is connected with an edge and such that each pair is connected with an edge and
each node belongs to at most one pair. each node belongs to at most one pair.
@ -787,10 +788,11 @@ maximum flow problem.
\subsubsection{Finding maximum matchings} \subsubsection{Finding maximum matchings}
The nodes in a bipartite graph can be always The nodes of a bipartite graph can be always
divided into two groups such that all edges divided into two groups such that all edges
of the graph go from the left group to the right group. of the graph go from the left group to the right group.
For example, consider the following bipartite graph: For example, in the following bipartite graph,
the groups are $\{1,2,3,4\}$ and $\{5,6,7,8\}$.
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.60] \begin{tikzpicture}[scale=0.60]
@ -811,8 +813,7 @@ For example, consider the following bipartite graph:
\path[draw,thick,-] (4) -- (7); \path[draw,thick,-] (4) -- (7);
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
The size of a maximum matching of the graph is 3:
In this graph, the size of a maximum matching is 3:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.60] \begin{tikzpicture}[scale=0.60]
\node[draw, circle] (1) at (2,4.5) {1}; \node[draw, circle] (1) at (2,4.5) {1};
@ -840,7 +841,7 @@ In this graph, the size of a maximum matching is 3:
We can reduce the bipartite maximum matching problem We can reduce the bipartite maximum matching problem
to the maximum flow problem by adding two new nodes to the maximum flow problem by adding two new nodes
to the graph: a source and a sink. to the graph: a source and a sink.
In addition, we add edges from the source We also add edges from the source
to each left node and from each right node to the sink. to each left node and from each right node to the sink.
After this, the maximum flow of the graph After this, the maximum flow of the graph
equals the maximum matching of the original graph. equals the maximum matching of the original graph.
@ -996,7 +997,7 @@ Next, let $X=\{2,4\}$ which yields $f(X)=\{7\}$:
In this case, $|X|=2$ and $|f(X)|=1$, In this case, $|X|=2$ and $|f(X)|=1$,
so the condition of Hall's theorem does not hold. so the condition of Hall's theorem does not hold.
This means that it is not possible to form This means that it is not possible to form
a perfect matching in the graph. a perfect matching for the graph.
This result is not surprising, because we already This result is not surprising, because we already
know that the maximum matching of the graph is 3 and not 4. know that the maximum matching of the graph is 3 and not 4.
@ -1115,7 +1116,7 @@ set is as follows:
\index{path cover} \index{path cover}
A \key{path cover} is a set of paths in a graph A \key{path cover} is a set of paths of a graph
such that each node of the graph belongs to at least one path. such that each node of the graph belongs to at least one path.
It turns out that in directed, acyclic graphs, It turns out that in directed, acyclic graphs,
we can reduce the problem of finding a minimum we can reduce the problem of finding a minimum
@ -1172,19 +1173,20 @@ Note that one of the paths only contains node 2,
so it is possible that a path does not contain any edges. so it is possible that a path does not contain any edges.
We can find a minimum node-disjoint path cover We can find a minimum node-disjoint path cover
by constructing a matching graph where each node by constructing a \emph{matching graph} where each node
of the original graph is represented by of the original graph is represented by
two nodes: a left node and a right node. two nodes: a left node and a right node.
There is an edge from a left node to a right node There is an edge from a left node to a right node
if there is a such an edge in the original graph. if there is a such an edge in the original graph.
In addition, the matching graph contains a source and a sink In addition, the matching graph contains a source and a sink,
such that there are edges from the source to all and there are edges from the source to all
left nodes and from all right nodes to the sink. left nodes and from all right nodes to the sink.
A maximum matching in the resulting graph corresponds A maximum matching of the resulting graph corresponds
to a minimum node-disjoint path cover in to a minimum node-disjoint path cover in
the original graph. the original graph.
For example, the following graph contains For example, the following matching graph
for the above graph contains
a maximum matching of size 4: a maximum matching of size 4:
\begin{center} \begin{center}
@ -1252,7 +1254,7 @@ A \key{general path cover} is a path cover
where a node can belong to more than one path. where a node can belong to more than one path.
A minimum general path cover may be smaller A minimum general path cover may be smaller
than a minimum node-disjoint path cover, than a minimum node-disjoint path cover,
because a node can used multiple times in paths. because a node can be used multiple times in paths.
Consider again the following graph: Consider again the following graph:
\begin{center} \begin{center}
\begin{tikzpicture}[scale=0.9] \begin{tikzpicture}[scale=0.9]
@ -1273,7 +1275,7 @@ Consider again the following graph:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
The minimum general path cover in this graph The minimum general path cover of this graph
consists of two paths. consists of two paths.
For example, the first path may be as follows: For example, the first path may be as follows:
\begin{center} \begin{center}