Corrections
This commit is contained in:
parent
88c2ee5f27
commit
c9460ad2d3
64
luku12.tex
64
luku12.tex
|
@ -1,6 +1,6 @@
|
||||||
\chapter{Graph search}
|
\chapter{Graph traversal}
|
||||||
|
|
||||||
This chapter introduces two fundamental
|
This chapter discusses two fundamental
|
||||||
graph algorithms:
|
graph algorithms:
|
||||||
depth-first search and breadth-first search.
|
depth-first search and breadth-first search.
|
||||||
Both algorithms are given a starting
|
Both algorithms are given a starting
|
||||||
|
@ -15,7 +15,7 @@ in which they visit the nodes.
|
||||||
\index{depth-first search}
|
\index{depth-first search}
|
||||||
|
|
||||||
\key{Depth-first search} (DFS)
|
\key{Depth-first search} (DFS)
|
||||||
is a straightforward graph search technique.
|
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
|
||||||
|
@ -24,14 +24,14 @@ the edges in 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
|
||||||
new nodes.
|
new nodes.
|
||||||
After this, it returns back to previous
|
After this, it returns to previous
|
||||||
nodes and begins to explore other parts of the graph.
|
nodes and begins to explore other parts of the graph.
|
||||||
The algorithm keeps track of visited nodes,
|
The algorithm keeps track of visited nodes,
|
||||||
so that it processes each node only once.
|
so that it processes each node only once.
|
||||||
|
|
||||||
\subsubsection*{Example}
|
\subsubsection*{Example}
|
||||||
|
|
||||||
Let's consider how depth-first search processes
|
Let us consider how depth-first search processes
|
||||||
the following graph:
|
the following graph:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}
|
\begin{tikzpicture}
|
||||||
|
@ -92,9 +92,9 @@ 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's time to return back.
|
so it is time to return to previous nodes.
|
||||||
Also the neighbors of nodes 3 and 2
|
Also the neighbors of nodes 3 and 2
|
||||||
have been visited, so we'll next proceed
|
have been visited, so we next move
|
||||||
from node 1 to node 4:
|
from node 1 to node 4:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}
|
\begin{tikzpicture}
|
||||||
|
@ -128,7 +128,7 @@ implemented using recursion.
|
||||||
The following function \texttt{dfs} begins
|
The following function \texttt{dfs} begins
|
||||||
a depth-first search at a given node.
|
a depth-first search at a given node.
|
||||||
The function assumes that the graph is
|
The function assumes that the graph is
|
||||||
stored as adjacency lists in array
|
stored as adjacency lists in an array
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
vector<int> v[N];
|
vector<int> v[N];
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
@ -175,7 +175,7 @@ have been visited.
|
||||||
|
|
||||||
\subsubsection*{Example}
|
\subsubsection*{Example}
|
||||||
|
|
||||||
Let's consider how the algorithm processes
|
Let us consider how the algorithm processes
|
||||||
the following graph:
|
the following graph:
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
|
@ -196,7 +196,7 @@ the following graph:
|
||||||
\path[draw,thick,-] (5) -- (6);
|
\path[draw,thick,-] (5) -- (6);
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
Assume again that the search begins at node 1.
|
Suppose again 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}
|
||||||
|
@ -224,7 +224,7 @@ from node 1 using a single edge:
|
||||||
\path[draw=red,thick,->,line width=2pt] (1) -- (4);
|
\path[draw=red,thick,->,line width=2pt] (1) -- (4);
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
After this, we procees to nodes 3 and 5:
|
After this, we proceed to nodes 3 and 5:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}
|
\begin{tikzpicture}
|
||||||
\node[draw, circle,fill=lightgray] (1) at (1,5) {$1$};
|
\node[draw, circle,fill=lightgray] (1) at (1,5) {$1$};
|
||||||
|
@ -301,10 +301,10 @@ and $m$ is the number of edges.
|
||||||
\subsubsection*{Implementation}
|
\subsubsection*{Implementation}
|
||||||
|
|
||||||
Breadth-first search is more difficult
|
Breadth-first search is more difficult
|
||||||
to implement than depth-first search
|
to implement than depth-first search,
|
||||||
because the algorithm visits nodes
|
because the algorithm visits nodes
|
||||||
in different parts in the graph.
|
in different parts of the graph.
|
||||||
A typical implementation is to maintain
|
A typical implementation is based on
|
||||||
a queue of nodes to be processed.
|
a queue of nodes to be processed.
|
||||||
At each step, the next node in the queue
|
At each step, the next node in the queue
|
||||||
will be processed.
|
will be processed.
|
||||||
|
@ -326,9 +326,9 @@ In addition, the code uses arrays
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
int z[N], e[N];
|
int z[N], e[N];
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
so that array \texttt{z} indicates
|
so that the array \texttt{z} indicates
|
||||||
which nodes the search already has visited
|
which nodes the search has already visited
|
||||||
and array \texttt{e} will contain the
|
and the array \texttt{e} will contain the
|
||||||
minimum distance to all nodes in the graph.
|
minimum distance to all nodes in the graph.
|
||||||
The search can be implemented as follows:
|
The search can be implemented as follows:
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
|
@ -347,12 +347,12 @@ while (!q.empty()) {
|
||||||
|
|
||||||
\section{Applications}
|
\section{Applications}
|
||||||
|
|
||||||
Using the graph search algorithms,
|
Using the graph traversal algorithms,
|
||||||
we can check many properties of the graph.
|
we can check many properties of the graph.
|
||||||
Usually, either depth-first search or
|
Usually, either depth-first search or
|
||||||
bredth-first search can be used,
|
bredth-first search can 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.
|
||||||
In the following applications we will
|
In the following applications we will
|
||||||
assume that the graph is undirected.
|
assume that the graph is undirected.
|
||||||
|
@ -403,18 +403,18 @@ the following nodes:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Since the search didn't visit all the nodes,
|
Since the search did not visit all the nodes,
|
||||||
we can conclude that the graph is not connected.
|
we can conclude that the graph is not connected.
|
||||||
In a similar way, we can also find all components
|
In a similar way, we can also find all connected components
|
||||||
in a graph by iterating trough the nodes and always
|
of a graph by iterating trough the nodes and always
|
||||||
starting a new depth-first search if the node
|
starting a new depth-first search if the current node
|
||||||
doesn't belong to a component.
|
does not belong to any component yet.
|
||||||
|
|
||||||
\subsubsection{Finding cycles}
|
\subsubsection{Finding cycles}
|
||||||
|
|
||||||
\index{cycle}
|
\index{cycle}
|
||||||
|
|
||||||
A graph contains a cycle if during a graph search,
|
A graph contains a cycle if during a graph traversal,
|
||||||
we find a node whose neighbor (other than the
|
we find a node whose neighbor (other than the
|
||||||
previous node in the current path) has already been
|
previous node in the current path) has already been
|
||||||
visited.
|
visited.
|
||||||
|
@ -442,7 +442,7 @@ For example, the graph
|
||||||
\end{center}
|
\end{center}
|
||||||
contains a cycle because when we move from
|
contains a cycle because when we move from
|
||||||
node 2 to node 5 it turns out
|
node 2 to node 5 it turns out
|
||||||
that the neighbor node 3 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$.
|
||||||
|
|
||||||
|
@ -452,7 +452,7 @@ in every component.
|
||||||
If a component contains $c$ nodes and no cycle,
|
If a component contains $c$ nodes and no cycle,
|
||||||
it must contain exactly $c-1$ edges.
|
it must contain exactly $c-1$ edges.
|
||||||
If there are $c$ or more edges, the component
|
If there are $c$ or more edges, the component
|
||||||
always contains a cycle.
|
surely contains a cycle.
|
||||||
|
|
||||||
\subsubsection{Bipartiteness check}
|
\subsubsection{Bipartiteness check}
|
||||||
|
|
||||||
|
@ -460,9 +460,9 @@ always contains a cycle.
|
||||||
|
|
||||||
A graph is bipartite if its nodes can be colored
|
A graph is bipartite if its nodes can be colored
|
||||||
using two colors so that there are no adjacent
|
using two colors so that there are no adjacent
|
||||||
nodes with same color.
|
nodes with the same color.
|
||||||
It is suprisingly easy to check if a graph
|
It is suprisingly easy to check if a graph
|
||||||
is bipartite using graph search algorithms.
|
is bipartite using graph traversal algorithms.
|
||||||
|
|
||||||
The idea is to color the starting node blue,
|
The idea is to color the starting node blue,
|
||||||
all its neighbors red, all their neighbors blue, and so on.
|
all its neighbors red, all their neighbors blue, and so on.
|
||||||
|
@ -490,7 +490,7 @@ For example, the graph
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
is not bipartite because a search from node 1
|
is not bipartite because a search from node 1
|
||||||
produces the following situation:
|
proceeds as follows:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}
|
\begin{tikzpicture}
|
||||||
\node[draw, circle,fill=red!40] (2) at (5,5) {$2$};
|
\node[draw, circle,fill=red!40] (2) at (5,5) {$2$};
|
||||||
|
@ -516,11 +516,11 @@ We notice that the color or both node 2 and node 5
|
||||||
is red, while they are adjacent nodes in the graph.
|
is red, while they are adjacent nodes in the graph.
|
||||||
Thus, the graph is not bipartite.
|
Thus, the graph is not bipartite.
|
||||||
|
|
||||||
This algorithm always works because when there
|
This algorithm always works, because when there
|
||||||
are only two colors available,
|
are only two colors available,
|
||||||
the color of the starting node in a component
|
the color of the starting node in a component
|
||||||
determines the colors of all other nodes in the component.
|
determines the colors of all other nodes in the component.
|
||||||
It doesn't make any difference whether the
|
It does not make any difference whether the
|
||||||
starting node is red or blue.
|
starting node is red or blue.
|
||||||
|
|
||||||
Note that in the general case,
|
Note that in the general case,
|
||||||
|
|
Loading…
Reference in New Issue