Improve language
This commit is contained in:
parent
7aad9cc8d9
commit
5a298088b9
|
@ -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});
|
||||||
|
|
|
@ -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$.
|
||||||
|
|
||||||
|
|
|
@ -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{Bellman–Ford algorithm}\footnote{The algorithm is named after
|
The \key{Bellman–Ford 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
|
||||||
Bellman–Ford algorithm finds the shortest distances
|
Bellman–Ford 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 Bellman–Ford algorithm can be also used to
|
The Bellman–Ford 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 Bellman–Ford 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 Bellman–Ford algorithm.
|
like the Bellman–Ford 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{Floyd–Warshall algorithm}
|
\section{Floyd–Warshall algorithm}
|
||||||
|
@ -602,9 +605,9 @@ at most one distance to the priority queue.
|
||||||
The \key{Floyd–Warshall algorithm}\footnote{The algorithm
|
The \key{Floyd–Warshall 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++) {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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?
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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 Ford–Fulkerson
|
Next we will discuss the Ford–Fulkerson
|
||||||
|
@ -160,10 +161,10 @@ The algorithm also helps us to understand
|
||||||
The \key{Ford–Fulkerson algorithm} \cite{for56} finds
|
The \key{Ford–Fulkerson 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 Ford–Fulkerson algorithm
|
It turns out that once the Ford–Fulkerson 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}
|
||||||
|
|
Loading…
Reference in New Issue