cphb/luku19.tex

664 lines
23 KiB
TeX
Raw Normal View History

2016-12-28 23:54:51 +01:00
\chapter{Paths and circuits}
2017-01-09 20:57:36 +01:00
This chapter focuses on two types of paths in a graph:
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-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.
It turns out that a simple rule based on node degrees
determines if a graph contains an Eulerian path,
and there is also an efficient algorithm for
finding the path.
On the contrary, finding a Hamiltonian path is a NP-hard
problem and thus no efficient algorithm is known for solving the problem.
\section{Eulerian path}
\index{Eulerian path}
An \key{Eulerian path} is a path
that goes exactly once through each edge in the graph.
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}
is an Eulerian path that begins and ends
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-01-09 20:57:36 +01:00
It turns out that the existence of Eulerian paths and circuits
depends on the degrees of the nodes in the graph.
The degree of a node is the number of its neighbours, i.e.,
the number of nodes that are connected with a direct edge.
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
An undirected graph has an Eulerian path if all the edges
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-01-09 20:57:36 +01:00
In the first case, each Eulerian path is also an Eulerian circuit.
In the second case, the odd-degree nodes are the starting
and ending nodes of an Eulerian path, and it 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-01-09 20:57:36 +01:00
the degree of nodes 1, 3 and 4 is 2,
and the degree of nodes 2 and 5 is 3.
Exactly two nodes have an even degree,
so there is an Eulerian path between nodes 2 and 5,
but the graph doesn't contain an Eulerian circuit.
In a directed graph, the situation is a bit more difficult.
In this case we should focus on indegree and outdegrees
of the nodes in the graph.
The indegree of a node is the number of edges that
end at the node,
and correspondingly, the outdegree is the number of
edges that begin at the node.
A directed graph contains an Eulerian path
if all the edges belong to the same strongly
connected component and
2016-12-28 23:54:51 +01:00
\begin{itemize}
2017-01-09 20:57:36 +01:00
\item each node has the same indegree and outdegree \emph{or}
\item in one node, indegree is one larger than outdegree,
in another node, outdegree is one larger than indegree,
and all other nodes have the same indegree and outdegree.
2016-12-28 23:54:51 +01:00
\end{itemize}
2017-01-09 20:57:36 +01:00
In the first case,
each Eulerian path is also an Eulerian circuit,
and in the second case, the graph only contains an Eulerian path
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}
\key{Hierholzer's algorithm} constructs an Eulerian circuit
in an undirected graph.
The algorithm assumes that all edges belong to
the same connected component,
and the degree of each node is even.
The algorithm can be implemented in $O(n+m)$ time.
First, the algorithm constructs a circuit that contains
some (not necessarily all) of the edges in the graph.
After this, the algorithm extends the circuit
step by step by adding subcircuits to it.
This continues until all edges have been added
and the Eulerian circuit is ready.
The algorithm extends the circuit by always choosing
a node $x$ that belongs to the circuit but has
some edges that are not included in the circuit.
The algorith constructs a new path from node $x$
that only contains edges that are not in the circuit.
Since the degree of each node is even,
sooner or later the path will return to node $x$
which creates a subcircuit.
If the graph contains two odd-degree nodes,
Hierholzer's algorithm can also be used for
constructing an Eulerian path by adding an
extra edge between the odd-degree nodes.
After this, we can first construct an Eulerian circuit
and then remove the extra edge,
which produces an Eulerian path in the original graph.
\subsubsection{Example}
2016-12-28 23:54:51 +01:00
\begin{samepage}
2017-01-09 20:57:36 +01:00
Let's 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-01-09 20:57:36 +01:00
Assume that the algorithm first creates a circuit
that begins at node 1.
One possible circuit is
$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
a subcircuit
2016-12-28 23:54:51 +01:00
$2 \rightarrow 5 \rightarrow 6 \rightarrow 2$:
\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-01-09 20:57:36 +01:00
Finally, the algorithm adds a subcircuit
2016-12-28 23:54:51 +01:00
$6 \rightarrow 3 \rightarrow 4 \rightarrow 7 \rightarrow 6$:
\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-01-09 20:57:36 +01:00
\section{Hamiltonian path}
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-01-09 20:57:36 +01:00
A \key{Hamiltonian path} is a path
that visits each node in the graph exactly once.
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-01-09 20:57:36 +01:00
No efficient way is known to check if a graph
contains a Hamiltonian path.
Still, in some special cases we can be certain
that the 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}
\key{Dirac's theorem}:
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}
\key{Ore's theorem}:
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-01-09 20:57:36 +01:00
A common feature in these theorems and other results is
that they guarantee that a Hamiltonian path exists
if the graph has \emph{a lot} of edges.
This makes sense because the more edges the graph has,
the more possibilities we have to construct a Hamiltonian graph.
\subsubsection{Construction}
Since there is no efficient way to check if a Hamiltonian
path exists, it is clear that there is also no method
for constructing the path efficiently, because otherwise
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
possibilities how to construct the path.
The time complexity of such an algorithm is at least $O(n!)$,
because there are $n!$ different ways to form a path
from $n$ nodes.
A more efficient solution is based on dynamic programming
(see Chapter 10.4).
The idea is to define a function $f(s,x)$,
where $s$ is a subset of nodes, and $x$
is one of the nodes in the subset.
The function indicates whether there is a Hamiltonian path
that visits the nodes in $s$ and ends at node $x$.
It is possible to implement this solution in $O(2^n n^2)$ time.
\section{De Bruijn sequence}
\index{De Bruijn sequence}
A \key{De Bruijn sequence} is a string that contains
every string of length $n$
exactly once as a substring, for a fixed
alphabet that consists of $k$ characters.
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
corresponds to an Eulerian circuit in a graph.
The idea is to construct the graph so that
each node contains a combination of $n-1$ characters
and each edge adds one character to the string.
The following graph corresponds to the example case:
2016-12-28 23:54:51 +01:00
\begin{center}
\begin{tikzpicture}
\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-01-09 20:57:36 +01:00
An Eulerian path in this graph produces a string
that contains all strings of length $n$.
The string contains the characters in the starting node,
and all character in the edges.
The starting node contains $n-1$ characters
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-01-09 20:57:36 +01:00
\section{Knight's tour}
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
following the rules of chess where the knight
visits each square exactly once.
The tour is \key{closed} if the knight finally
returns to the starting square and
otherwise the tour is \key{open}.
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
For example, here's a 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
whose nodes represent the squares of the board,
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-01-09 20:57:36 +01:00
A natural way to solve the problem is to use backtracking.
The search can be made more efficient by using
\key{heuristics} that attempts to guide the knight so that
a complete tour will be found quickly.
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
\subsubsection{Warnsdorff's rule}
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
\index{heuristic}
\index{Warnsdorff's rule}
2016-12-28 23:54:51 +01:00
2017-01-09 20:57:36 +01:00
\key{Warnsdorff's rule} is a simple and good heuristic
for finding a knight's tour.
Using the rule, it is possible to efficiently find a tour
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-01-09 20:57:36 +01:00
For example, in the following case there are five
possible squares where the knight can move:
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-01-09 20:57:36 +01:00
In this case, Warnsdorff's rule moves the knight to square $a$,
because after this choice there is only a single possible move.
The other choices would move the knight to squares where
there are three moves available.
2016-12-28 23:54:51 +01:00