cphb/chapter19.tex

675 lines
24 KiB
TeX
Raw Permalink Normal View History

2016-12-28 23:54:51 +01:00
\chapter{Paths and circuits}
2017-02-18 14:14:04 +01:00
This chapter focuses on two types of paths in graphs:
2016-12-28 23:54:51 +01:00
\begin{itemize}
2017-01-09 20:57:36 +01:00
\item An \key{Eulerian path} is a path that
goes through each edge exactly once.
\item A \key{Hamiltonian path} is a path
that visits each node exactly once.
2016-12-28 23:54:51 +01:00
\end{itemize}
2017-05-07 20:18:56 +02:00
2017-01-09 20:57:36 +01:00
While Eulerian and Hamiltonian paths look like
similar concepts at first glance,
the computational problems related to them
are very different.
2017-02-06 23:12:31 +01:00
It turns out that there is a simple rule that
2017-05-07 20:18:56 +02:00
determines whether a graph contains an Eulerian path,
2017-02-18 14:14:04 +01:00
and there is also an efficient algorithm to
2017-02-28 00:40:59 +01:00
find such a path if it exists.
2017-02-06 23:12:31 +01:00
On the contrary, checking the existence of a Hamiltonian path is a NP-hard
2017-05-07 20:18:56 +02:00
problem, and no efficient algorithm is known for solving the problem.
2017-01-09 20:57:36 +01:00
2017-02-20 22:23:10 +01:00
\section{Eulerian paths}
2017-01-09 20:57:36 +01:00
\index{Eulerian path}
2017-02-27 21:13:33 +01:00
An \key{Eulerian path}\footnote{L. Euler studied such paths in 1736
2017-02-25 17:57:13 +01:00
when he solved the famous Königsberg bridge problem.
This was the birth of graph theory.} is a path
2017-05-07 20:18:56 +02:00
that goes exactly once through each edge of the graph.
2017-01-09 20:57:36 +01:00
For example, the graph
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (5);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (4) -- (5);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
has an Eulerian path from node 2 to node 5:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (5);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (4) -- (5);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]north:1.}] {} (1);
\path[draw=red,thick,->,line width=2pt] (1) -- node[font=\small,label={[red]left:2.}] {} (4);
\path[draw=red,thick,->,line width=2pt] (4) -- node[font=\small,label={[red]south:3.}] {} (5);
\path[draw=red,thick,->,line width=2pt] (5) -- node[font=\small,label={[red]left:4.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]north:5.}] {} (3);
\path[draw=red,thick,->,line width=2pt] (3) -- node[font=\small,label={[red]south:6.}] {} (5);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
\index{Eulerian circuit}
An \key{Eulerian circuit}
2017-02-06 23:12:31 +01:00
is an Eulerian path that starts and ends
2017-01-09 20:57:36 +01:00
at the same node.
For example, the graph
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (5);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (2) -- (4);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
has an Eulerian circuit that starts and ends at node 1:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (5);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (2) -- (4);
\path[draw=red,thick,->,line width=2pt] (1) -- node[font=\small,label={[red]left:1.}] {} (4);
\path[draw=red,thick,->,line width=2pt] (4) -- node[font=\small,label={[red]south:2.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]right:3.}] {} (5);
\path[draw=red,thick,->,line width=2pt] (5) -- node[font=\small,label={[red]south:4.}] {} (3);
\path[draw=red,thick,->,line width=2pt] (3) -- node[font=\small,label={[red]north:5.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]north:6.}] {} (1);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
\subsubsection{Existence}
2016-12-28 23:54:51 +01:00
2017-02-06 23:12:31 +01:00
The existence of Eulerian paths and circuits
2017-05-29 20:46:04 +02:00
depends on the degrees of the nodes.
First, an undirected graph has an Eulerian path
exactly when all the edges
2017-01-09 20:57:36 +01:00
belong to the same connected component and
2016-12-28 23:54:51 +01:00
\begin{itemize}
2017-01-09 20:57:36 +01:00
\item the degree of each node is even \emph{or}
\item the degree of exactly two nodes is odd,
and the degree of all other nodes is even.
2016-12-28 23:54:51 +01:00
\end{itemize}
2017-05-29 20:46:04 +02:00
In the first case, each Eulerian path is also an Eulerian circuit.
2017-01-09 20:57:36 +01:00
In the second case, the odd-degree nodes are the starting
2017-02-06 23:12:31 +01:00
and ending nodes of an Eulerian path which is not an Eulerian circuit.
2016-12-28 23:54:51 +01:00
\begin{samepage}
2017-01-09 20:57:36 +01:00
For example, in the graph
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (5);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (4) -- (5);
\end{tikzpicture}
\end{center}
\end{samepage}
2017-02-06 23:12:31 +01:00
nodes 1, 3 and 4 have a degree of 2,
and nodes 2 and 5 have a degree of 3.
2017-04-03 00:21:47 +02:00
Exactly two nodes have an odd degree,
2017-01-09 20:57:36 +01:00
so there is an Eulerian path between nodes 2 and 5,
2017-02-06 23:12:31 +01:00
but the graph does not contain an Eulerian circuit.
2017-01-09 20:57:36 +01:00
2017-02-06 23:12:31 +01:00
In a directed graph,
2017-02-18 14:14:04 +01:00
we focus on indegrees and outdegrees
2017-05-29 20:46:04 +02:00
of the nodes.
2017-01-09 20:57:36 +01:00
A directed graph contains an Eulerian path
2018-07-03 13:58:22 +02:00
exactly when all the edges belong to the same
2017-01-09 20:57:36 +01:00
connected component and
2016-12-28 23:54:51 +01:00
\begin{itemize}
2017-02-18 14:14:04 +01:00
\item in each node, the indegree equals the outdegree, \emph{or}
\item in one node, the indegree is one larger than the outdegree,
in another node, the outdegree is one larger than the indegree,
2017-05-07 20:18:56 +02:00
and in all other nodes, the indegree equals the outdegree.
2016-12-28 23:54:51 +01:00
\end{itemize}
2017-05-29 20:46:04 +02:00
In the first case, each Eulerian path
2017-02-06 23:12:31 +01:00
is also an Eulerian circuit,
and in the second case, the graph contains an Eulerian path
2017-01-09 20:57:36 +01:00
that begins at the node whose outdegree is larger
and ends at the node whose indegree is larger.
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
For example, in the graph
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,->,>=latex] (1) -- (2);
\path[draw,thick,->,>=latex] (2) -- (3);
\path[draw,thick,->,>=latex] (4) -- (1);
\path[draw,thick,->,>=latex] (3) -- (5);
\path[draw,thick,->,>=latex] (2) -- (5);
\path[draw,thick,->,>=latex] (5) -- (4);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
nodes 1, 3 and 4 have both indegree 1 and outdegree 1,
node 2 has indegree 1 and outdegree 2,
and node 5 has indegree 2 and outdegree 1.
Hence, the graph contains an Eulerian path
from node 2 to node 5:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (5);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (4) -- (5);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]north:1.}] {} (3);
\path[draw=red,thick,->,line width=2pt] (3) -- node[font=\small,label={[red]south:2.}] {} (5);
\path[draw=red,thick,->,line width=2pt] (5) -- node[font=\small,label={[red]south:3.}] {} (4);
\path[draw=red,thick,->,line width=2pt] (4) -- node[font=\small,label={[red]left:4.}] {} (1);
\path[draw=red,thick,->,line width=2pt] (1) -- node[font=\small,label={[red]north:5.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]left:6.}] {} (5);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
\subsubsection{Hierholzer's algorithm}
\index{Hierholzer's algorithm}
2017-02-25 17:57:13 +01:00
\key{Hierholzer's algorithm}\footnote{The algorithm was published
in 1873 after Hierholzer's death \cite{hie73}.} is an efficient
2017-02-18 14:14:04 +01:00
method for constructing
an Eulerian circuit.
The algorithm consists of several rounds,
each of which adds new edges to the circuit.
Of course, we assume that the graph contains
an Eulerian circuit; otherwise Hierholzer's
algorithm cannot find it.
2017-01-09 20:57:36 +01:00
First, the algorithm constructs a circuit that contains
2017-05-07 20:18:56 +02:00
some (not necessarily all) of the edges of the graph.
2017-01-09 20:57:36 +01:00
After this, the algorithm extends the circuit
step by step by adding subcircuits to it.
2017-02-06 23:12:31 +01:00
The process continues until all edges have been added
to the circuit.
2017-01-09 20:57:36 +01:00
2017-02-18 14:14:04 +01:00
The algorithm extends the circuit by always finding
2017-01-09 20:57:36 +01:00
a node $x$ that belongs to the circuit but has
2017-02-18 14:14:04 +01:00
an outgoing edge that is not included in the circuit.
2017-02-06 23:12:31 +01:00
The algorithm constructs a new path from node $x$
2017-02-18 14:14:04 +01:00
that only contains edges that are not yet in the circuit.
Sooner or later,
2017-05-29 20:46:04 +02:00
the path will return to node $x$,
2017-01-09 20:57:36 +01:00
which creates a subcircuit.
2017-02-18 14:14:04 +01:00
If the graph only contains an Eulerian path,
we can still use Hierholzer's algorithm
to find it by adding an extra edge to the graph
and removing the edge after the circuit
has been constructed.
For example, in an undirected graph,
we add the extra edge between the two
odd-degree nodes.
Next we will see how Hierholzer's algorithm
2017-05-07 20:18:56 +02:00
constructs an Eulerian circuit for an undirected graph.
2017-01-09 20:57:36 +01:00
\subsubsection{Example}
2016-12-28 23:54:51 +01:00
\begin{samepage}
2017-02-06 23:12:31 +01:00
Let us consider the following graph:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (3,5) {$1$};
\node[draw, circle] (2) at (1,3) {$2$};
\node[draw, circle] (3) at (3,3) {$3$};
\node[draw, circle] (4) at (5,3) {$4$};
\node[draw, circle] (5) at (1,1) {$5$};
\node[draw, circle] (6) at (3,1) {$6$};
\node[draw, circle] (7) at (5,1) {$7$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (2) -- (6);
\path[draw,thick,-] (3) -- (4);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (4) -- (7);
\path[draw,thick,-] (5) -- (6);
\path[draw,thick,-] (6) -- (7);
\end{tikzpicture}
\end{center}
\end{samepage}
\begin{samepage}
2017-02-18 14:14:04 +01:00
Suppose that the algorithm first creates a circuit
2017-01-09 20:57:36 +01:00
that begins at node 1.
2017-02-06 23:12:31 +01:00
A possible circuit is
2017-01-09 20:57:36 +01:00
$1 \rightarrow 2 \rightarrow 3 \rightarrow 1$:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (3,5) {$1$};
\node[draw, circle] (2) at (1,3) {$2$};
\node[draw, circle] (3) at (3,3) {$3$};
\node[draw, circle] (4) at (5,3) {$4$};
\node[draw, circle] (5) at (1,1) {$5$};
\node[draw, circle] (6) at (3,1) {$6$};
\node[draw, circle] (7) at (5,1) {$7$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (2) -- (6);
\path[draw,thick,-] (3) -- (4);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (4) -- (7);
\path[draw,thick,-] (5) -- (6);
\path[draw,thick,-] (6) -- (7);
\path[draw=red,thick,->,line width=2pt] (1) -- node[font=\small,label={[red]north:1.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]north:2.}] {} (3);
\path[draw=red,thick,->,line width=2pt] (3) -- node[font=\small,label={[red]east:3.}] {} (1);
\end{tikzpicture}
\end{center}
\end{samepage}
2017-01-09 20:57:36 +01:00
After this, the algorithm adds
2017-02-06 23:12:31 +01:00
the subcircuit
$2 \rightarrow 5 \rightarrow 6 \rightarrow 2$
to the circuit:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (3,5) {$1$};
\node[draw, circle] (2) at (1,3) {$2$};
\node[draw, circle] (3) at (3,3) {$3$};
\node[draw, circle] (4) at (5,3) {$4$};
\node[draw, circle] (5) at (1,1) {$5$};
\node[draw, circle] (6) at (3,1) {$6$};
\node[draw, circle] (7) at (5,1) {$7$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (2) -- (6);
\path[draw,thick,-] (3) -- (4);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (4) -- (7);
\path[draw,thick,-] (5) -- (6);
\path[draw,thick,-] (6) -- (7);
\path[draw=red,thick,->,line width=2pt] (1) -- node[font=\small,label={[red]north:1.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]west:2.}] {} (5);
\path[draw=red,thick,->,line width=2pt] (5) -- node[font=\small,label={[red]south:3.}] {} (6);
\path[draw=red,thick,->,line width=2pt] (6) -- node[font=\small,label={[red]north:4.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]north:5.}] {} (3);
\path[draw=red,thick,->,line width=2pt] (3) -- node[font=\small,label={[red]east:6.}] {} (1);
\end{tikzpicture}
\end{center}
2017-02-06 23:12:31 +01:00
Finally, the algorithm adds the subcircuit
$6 \rightarrow 3 \rightarrow 4 \rightarrow 7 \rightarrow 6$
to the circuit:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (3,5) {$1$};
\node[draw, circle] (2) at (1,3) {$2$};
\node[draw, circle] (3) at (3,3) {$3$};
\node[draw, circle] (4) at (5,3) {$4$};
\node[draw, circle] (5) at (1,1) {$5$};
\node[draw, circle] (6) at (3,1) {$6$};
\node[draw, circle] (7) at (5,1) {$7$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (1) -- (3);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (2) -- (6);
\path[draw,thick,-] (3) -- (4);
\path[draw,thick,-] (3) -- (6);
\path[draw,thick,-] (4) -- (7);
\path[draw,thick,-] (5) -- (6);
\path[draw,thick,-] (6) -- (7);
\path[draw=red,thick,->,line width=2pt] (1) -- node[font=\small,label={[red]north:1.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]west:2.}] {} (5);
\path[draw=red,thick,->,line width=2pt] (5) -- node[font=\small,label={[red]south:3.}] {} (6);
\path[draw=red,thick,->,line width=2pt] (6) -- node[font=\small,label={[red]east:4.}] {} (3);
\path[draw=red,thick,->,line width=2pt] (3) -- node[font=\small,label={[red]north:5.}] {} (4);
\path[draw=red,thick,->,line width=2pt] (4) -- node[font=\small,label={[red]east:6.}] {} (7);
\path[draw=red,thick,->,line width=2pt] (7) -- node[font=\small,label={[red]south:7.}] {} (6);
\path[draw=red,thick,->,line width=2pt] (6) -- node[font=\small,label={[red]right:8.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]north:9.}] {} (3);
\path[draw=red,thick,->,line width=2pt] (3) -- node[font=\small,label={[red]east:10.}] {} (1);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
Now all edges are included in the circuit,
so we have successfully constructed an Eulerian circuit.
2016-12-28 23:54:51 +01:00
2017-02-20 22:23:10 +01:00
\section{Hamiltonian paths}
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
\index{Hamiltonian path}
2016-12-28 23:54:51 +01:00
2017-02-26 10:29:50 +01:00
A \key{Hamiltonian path}
%\footnote{W. R. Hamilton (1805--1865) was an Irish mathematician.}
is a path
2017-05-07 20:18:56 +02:00
that visits each node of the graph exactly once.
2017-01-09 20:57:36 +01:00
For example, the graph
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (5);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (4) -- (5);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
contains a Hamiltonian path from node 1 to node 3:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (5);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (4) -- (5);
\path[draw=red,thick,->,line width=2pt] (1) -- node[font=\small,label={[red]left:1.}] {} (4);
\path[draw=red,thick,->,line width=2pt] (4) -- node[font=\small,label={[red]south:2.}] {} (5);
\path[draw=red,thick,->,line width=2pt] (5) -- node[font=\small,label={[red]left:3.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]north:4.}] {} (3);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
\index{Hamiltonian circuit}
If a Hamiltonian path begins and ends at the same node,
it is called a \key{Hamiltonian circuit}.
The graph above also has an Hamiltonian circuit
that begins and ends at node 1:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.9]
\node[draw, circle] (1) at (1,5) {$1$};
\node[draw, circle] (2) at (3,5) {$2$};
\node[draw, circle] (3) at (5,4) {$3$};
\node[draw, circle] (4) at (1,3) {$4$};
\node[draw, circle] (5) at (3,3) {$5$};
\path[draw,thick,-] (1) -- (2);
\path[draw,thick,-] (2) -- (3);
\path[draw,thick,-] (1) -- (4);
\path[draw,thick,-] (3) -- (5);
\path[draw,thick,-] (2) -- (5);
\path[draw,thick,-] (4) -- (5);
\path[draw=red,thick,->,line width=2pt] (1) -- node[font=\small,label={[red]north:1.}] {} (2);
\path[draw=red,thick,->,line width=2pt] (2) -- node[font=\small,label={[red]north:2.}] {} (3);
\path[draw=red,thick,->,line width=2pt] (3) -- node[font=\small,label={[red]south:3.}] {} (5);
\path[draw=red,thick,->,line width=2pt] (5) -- node[font=\small,label={[red]south:4.}] {} (4);
\path[draw=red,thick,->,line width=2pt] (4) -- node[font=\small,label={[red]left:5.}] {} (1);
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
\subsubsection{Existence}
2016-12-28 23:54:51 +01:00
2017-02-06 23:12:31 +01:00
No efficient method is known for testing if a graph
2017-05-07 20:18:56 +02:00
contains a Hamiltonian path, and the problem is NP-hard.
Still, in some special cases, we can be certain
that a graph contains a Hamiltonian path.
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
A simple observation is that if the graph is complete,
i.e., there is an edge between all pairs of nodes,
it also contains a Hamiltonian path.
Also stronger results have been achieved:
2016-12-28 23:54:51 +01:00
\begin{itemize}
\item
2017-01-09 20:57:36 +01:00
\index{Dirac's theorem}
2017-02-26 10:29:50 +01:00
\key{Dirac's theorem}: %\cite{dir52}
2017-01-09 20:57:36 +01:00
If the degree of each node is at least $n/2$,
the graph contains a Hamiltonian path.
2016-12-28 23:54:51 +01:00
\item
2017-01-09 20:57:36 +01:00
\index{Ore's theorem}
2017-02-26 10:29:50 +01:00
\key{Ore's theorem}: %\cite{ore60}
2017-01-09 20:57:36 +01:00
If the sum of degrees of each non-adjacent pair of nodes
is at least $n$,
the graph contains a Hamiltonian path.
2016-12-28 23:54:51 +01:00
\end{itemize}
2017-02-18 14:14:04 +01:00
A common property in these theorems and other results is
2017-05-29 20:46:04 +02:00
that they guarantee the existence of a Hamiltonian path
2017-02-18 14:14:04 +01:00
if the graph has \emph{a large number} of edges.
2017-02-06 23:12:31 +01:00
This makes sense, because the more edges the graph contains,
2017-02-28 00:40:59 +01:00
the more possibilities there is to construct a Hamiltonian path.
2017-01-09 20:57:36 +01:00
\subsubsection{Construction}
Since there is no efficient way to check if a Hamiltonian
path exists, it is clear that there is also no method
2017-05-07 20:18:56 +02:00
to efficiently construct the path, because otherwise
2017-01-09 20:57:36 +01:00
we could just try to construct the path and see
whether it exists.
A simple way to search for a Hamiltonian path is
to use a backtracking algorithm that goes through all
2017-02-06 23:12:31 +01:00
possible ways to construct the path.
2017-01-09 20:57:36 +01:00
The time complexity of such an algorithm is at least $O(n!)$,
2017-02-06 23:12:31 +01:00
because there are $n!$ different ways to choose the order of $n$ nodes.
2017-01-09 20:57:36 +01:00
A more efficient solution is based on dynamic programming
2017-05-29 20:46:04 +02:00
(see Chapter 10.5).
The idea is to calculate values
of a function $\texttt{possible}(S,x)$,
where $S$ is a subset of nodes and $x$
is one of the nodes.
2017-01-09 20:57:36 +01:00
The function indicates whether there is a Hamiltonian path
2017-05-29 20:46:04 +02:00
that visits the nodes of $S$ and ends at node $x$.
2017-01-09 20:57:36 +01:00
It is possible to implement this solution in $O(2^n n^2)$ time.
2017-02-20 22:23:10 +01:00
\section{De Bruijn sequences}
2017-01-09 20:57:36 +01:00
\index{De Bruijn sequence}
2017-02-26 10:29:50 +01:00
A \key{De Bruijn sequence}
is a string that contains
2017-01-09 20:57:36 +01:00
every string of length $n$
exactly once as a substring, for a fixed
2017-02-18 14:14:04 +01:00
alphabet of $k$ characters.
2017-01-09 20:57:36 +01:00
The length of such a string is
$k^n+n-1$ characters.
For example, when $n=3$ and $k=2$,
an example of a De Bruijn sequence is
2016-12-28 23:54:51 +01:00
\[0001011100.\]
2017-01-09 20:57:36 +01:00
The substrings of this string are all
combinations of three bits:
000, 001, 010, 011, 100, 101, 110 and 111.
It turns out that each De Bruijn sequence
2017-04-19 20:16:50 +02:00
corresponds to an Eulerian path in a graph.
2017-05-29 20:46:04 +02:00
The idea is to construct a graph where
2017-05-07 20:18:56 +02:00
each node contains a string of $n-1$ characters
2017-01-09 20:57:36 +01:00
and each edge adds one character to the string.
2017-05-29 20:46:04 +02:00
The following graph corresponds to the above scenario:
2016-12-28 23:54:51 +01:00
\begin{center}
2017-02-25 17:57:13 +01:00
\begin{tikzpicture}[scale=0.8]
2016-12-28 23:54:51 +01:00
\node[draw, circle] (00) at (-3,0) {00};
\node[draw, circle] (11) at (3,0) {11};
\node[draw, circle] (01) at (0,2) {01};
\node[draw, circle] (10) at (0,-2) {10};
\path[draw,thick,->] (00) edge [bend left=20] node[font=\small,label=1] {} (01);
\path[draw,thick,->] (01) edge [bend left=20] node[font=\small,label=1] {} (11);
\path[draw,thick,->] (11) edge [bend left=20] node[font=\small,label=below:0] {} (10);
\path[draw,thick,->] (10) edge [bend left=20] node[font=\small,label=below:0] {} (00);
\path[draw,thick,->] (01) edge [bend left=30] node[font=\small,label=right:0] {} (10);
\path[draw,thick,->] (10) edge [bend left=30] node[font=\small,label=left:1] {} (01);
\path[draw,thick,-] (00) edge [loop left] node[font=\small,label=below:0] {} (00);
\path[draw,thick,-] (11) edge [loop right] node[font=\small,label=below:1] {} (11);
\end{tikzpicture}
\end{center}
2017-02-18 14:14:04 +01:00
An Eulerian path in this graph corresponds to a string
2017-01-09 20:57:36 +01:00
that contains all strings of length $n$.
2017-02-18 14:14:04 +01:00
The string contains the characters of the starting node
2017-05-07 20:18:56 +02:00
and all characters of the edges.
2017-02-06 23:12:31 +01:00
The starting node has $n-1$ characters
2017-01-09 20:57:36 +01:00
and there are $k^n$ characters in the edges,
so the length of the string is $k^n+n-1$.
2016-12-28 23:54:51 +01:00
2017-02-20 22:23:10 +01:00
\section{Knight's tours}
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
\index{knight's tour}
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
A \key{knight's tour} is a sequence of moves
of a knight on an $n \times n$ chessboard
2017-02-06 23:12:31 +01:00
following the rules of chess such that the knight
2017-01-09 20:57:36 +01:00
visits each square exactly once.
2017-05-07 20:18:56 +02:00
A knight's tour is called a \emph{closed} tour
if the knight finally returns to the starting square and
otherwise it is called an \emph{open} tour.
2016-12-28 23:54:51 +01:00
2017-02-06 23:12:31 +01:00
For example, here is an open knight's tour on a $5 \times 5$ board:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.7]
\draw (0,0) grid (5,5);
\node at (0.5,4.5) {$1$};
\node at (1.5,4.5) {$4$};
\node at (2.5,4.5) {$11$};
\node at (3.5,4.5) {$16$};
\node at (4.5,4.5) {$25$};
\node at (0.5,3.5) {$12$};
\node at (1.5,3.5) {$17$};
\node at (2.5,3.5) {$2$};
\node at (3.5,3.5) {$5$};
\node at (4.5,3.5) {$10$};
\node at (0.5,2.5) {$3$};
\node at (1.5,2.5) {$20$};
\node at (2.5,2.5) {$7$};
\node at (3.5,2.5) {$24$};
\node at (4.5,2.5) {$15$};
\node at (0.5,1.5) {$18$};
\node at (1.5,1.5) {$13$};
\node at (2.5,1.5) {$22$};
\node at (3.5,1.5) {$9$};
\node at (4.5,1.5) {$6$};
\node at (0.5,0.5) {$21$};
\node at (1.5,0.5) {$8$};
\node at (2.5,0.5) {$19$};
\node at (3.5,0.5) {$14$};
\node at (4.5,0.5) {$23$};
\end{tikzpicture}
\end{center}
2017-01-09 20:57:36 +01:00
A knight's tour corresponds to a Hamiltonian path in a graph
2017-05-07 20:18:56 +02:00
whose nodes represent the squares of the board,
2017-01-09 20:57:36 +01:00
and two nodes are connected with an edge if a knight
can move between the squares according to the rules of chess.
2016-12-28 23:54:51 +01:00
2017-02-06 23:12:31 +01:00
A natural way to construct a knight's tour is to use backtracking.
2017-01-09 20:57:36 +01:00
The search can be made more efficient by using
2017-05-07 20:18:56 +02:00
\emph{heuristics} that attempt to guide the knight so that
2017-01-09 20:57:36 +01:00
a complete tour will be found quickly.
2016-12-28 23:54:51 +01:00
2017-02-25 17:58:29 +01:00
\subsubsection{Warnsdorf's rule}
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
\index{heuristic}
2017-02-25 17:58:29 +01:00
\index{Warnsdorf's rule}
2016-12-28 23:54:51 +01:00
\key{Warnsdorf's rule} is a simple and effective heuristic
for finding a knight's tour\footnote{This heuristic was proposed
in Warnsdorf's book \cite{war23} in 1823. There are
also polynomial algorithms for finding knight's tours
\cite{par97}, but they are more complicated.}.
2017-02-06 23:12:31 +01:00
Using the rule, it is possible to efficiently construct a tour
2017-01-09 20:57:36 +01:00
even on a large board.
The idea is to always move the knight so that it ends up
in a square where the number of possible moves is as
\emph{small} as possible.
2016-12-28 23:54:51 +01:00
2017-05-07 20:18:56 +02:00
For example, in the following situation, there are five
2017-05-29 20:46:04 +02:00
possible squares to which the knight can move (squares $a \ldots e$):
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}[scale=0.7]
\draw (0,0) grid (5,5);
\node at (0.5,4.5) {$1$};
\node at (2.5,3.5) {$2$};
\node at (4.5,4.5) {$a$};
\node at (0.5,2.5) {$b$};
\node at (4.5,2.5) {$e$};
\node at (1.5,1.5) {$c$};
\node at (3.5,1.5) {$d$};
\end{tikzpicture}
\end{center}
2017-02-25 17:58:29 +01:00
In this situation, Warnsdorf's rule moves the knight to square $a$,
2017-02-06 23:12:31 +01:00
because after this choice, there is only a single possible move.
2017-01-09 20:57:36 +01:00
The other choices would move the knight to squares where
2017-02-06 23:12:31 +01:00
there would be three moves available.
2016-12-28 23:54:51 +01:00