641 lines
19 KiB
TeX
641 lines
19 KiB
TeX
\chapter{Graph search}
|
|
|
|
Tässä luvussa tutustumme
|
|
syvyyshakuun ja leveyshakuun, jotka
|
|
ovat keskeisiä menetelmiä verkon läpikäyntiin.
|
|
Molemmat algoritmit lähtevät liikkeelle
|
|
tietystä alkusolmusta ja
|
|
käyvät läpi kaikki solmut,
|
|
joihin alkusolmusta pääsee.
|
|
Algoritmien erona on,
|
|
missä järjestyksessä ne kulkevat verkossa.
|
|
|
|
\section{Syvyyshaku}
|
|
|
|
\index{syvyyshaku@syvyyshaku}
|
|
|
|
\key{Syvyyshaku}
|
|
on suoraviivainen menetelmä verkon läpikäyntiin.
|
|
Algoritmi lähtee liikkeelle tietystä
|
|
verkon solmusta ja etenee siitä
|
|
kaikkiin solmuihin, jotka ovat
|
|
saavutettavissa kaaria kulkemalla.
|
|
|
|
Syvyyshaku etenee verkossa syvyyssuuntaisesti
|
|
eli kulkee eteenpäin verkossa niin kauan
|
|
kuin vastaan tulee uusia solmuja.
|
|
Tämän jälkeen haku perääntyy kokeilemaan
|
|
muita suuntia.
|
|
Algoritmi pitää kirjaa vierailemistaan solmuista,
|
|
jotta se käsittelee kunkin solmun vain kerran.
|
|
|
|
\subsubsection*{Esimerkki}
|
|
|
|
Tarkastellaan syvyyshaun toimintaa
|
|
seuraavassa verkossa:
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\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);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Syvyyshaku voi lähteä liikkeelle
|
|
mistä tahansa solmusta,
|
|
mutta oletetaan nyt,
|
|
että haku lähtee liikkeelle solmusta 1.
|
|
|
|
Solmun 1 naapurit ovat solmut 2 ja 4,
|
|
joista haku etenee ensin solmuun 2:
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle,fill=lightgray] (1) at (1,5) {$1$};
|
|
\node[draw, circle,fill=lightgray] (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=red,thick,->,line width=2pt] (1) -- (2);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Tämän jälkeen haku etenee vastaavasti
|
|
solmuihin 3 ja 5:
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle,fill=lightgray] (1) at (1,5) {$1$};
|
|
\node[draw, circle,fill=lightgray] (2) at (3,5) {$2$};
|
|
\node[draw, circle,fill=lightgray] (3) at (5,4) {$3$};
|
|
\node[draw, circle] (4) at (1,3) {$4$};
|
|
\node[draw, circle,fill=lightgray] (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=red,thick,->,line width=2pt] (1) -- (2);
|
|
\path[draw=red,thick,->,line width=2pt] (2) -- (3);
|
|
\path[draw=red,thick,->,line width=2pt] (3) -- (5);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Solmun 5 naapurit ovat 2 ja 3,
|
|
mutta haku on käynyt jo molemmissa,
|
|
joten on aika peruuttaa taaksepäin.
|
|
Myös solmujen 3 ja 2 naapurit on käyty,
|
|
joten haku peruuttaa solmuun 1 asti.
|
|
Siitä lähtee kaari, josta pääsee
|
|
solmuun 4:
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle,fill=lightgray] (1) at (1,5) {$1$};
|
|
\node[draw, circle,fill=lightgray] (2) at (3,5) {$2$};
|
|
\node[draw, circle,fill=lightgray] (3) at (5,4) {$3$};
|
|
\node[draw, circle,fill=lightgray] (4) at (1,3) {$4$};
|
|
\node[draw, circle,fill=lightgray] (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=red,thick,->,line width=2pt] (1) -- (4);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Tämän jälkeen haku päättyy,
|
|
koska se on käynyt kaikissa solmuissa.
|
|
|
|
Syvyyshaun aikavaativuus on $O(n+m)$,
|
|
missä $n$ on solmujen määrä ja $m$ on kaarten määrä,
|
|
koska haku käsittelee kerran jokaisen solmun ja kaaren.
|
|
|
|
\subsubsection*{Toteutus}
|
|
|
|
Syvyyshaku on yleensä mukavinta toteuttaa
|
|
rekursiolla.
|
|
Seuraava funktio \texttt{haku}
|
|
suorittaa syvyyshaun sille parametrina
|
|
annetusta solmusta lähtien.
|
|
Funktio olettaa, että
|
|
verkko on tallennettu vieruslistoina
|
|
taulukkoon
|
|
\begin{lstlisting}
|
|
vector<int> v[N];
|
|
\end{lstlisting}
|
|
ja pitää lisäksi yllä taulukkoa
|
|
\begin{lstlisting}
|
|
int z[N];
|
|
\end{lstlisting}
|
|
joka kertoo, missä solmuissa haku on käynyt.
|
|
Alussa taulukon jokainen arvo on 0,
|
|
ja kun haku saapuu solmuun $s$,
|
|
kohtaan \texttt{z}[$s$] merkitään 1.
|
|
Funktion toteutus on seuraavanlainen:
|
|
\begin{lstlisting}
|
|
void haku(int s) {
|
|
if (z[s]) return;
|
|
z[s] = 1;
|
|
// solmun s käsittely tähän
|
|
for (auto u: v[s]) {
|
|
haku(u);
|
|
}
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\section{Leveyshaku}
|
|
|
|
\index{leveyshaku@leveyshaku}
|
|
|
|
\key{Leveyshaku}
|
|
käy solmut läpi järjestyksessä sen mukaan,
|
|
kuinka kaukana ne ovat alkusolmusta.
|
|
Niinpä leveyshaun avulla pystyy laskemaan
|
|
etäisyyden alkusolmusta kaikkiin
|
|
muihin solmuihin.
|
|
Leveyshaku on kuitenkin vaikeampi
|
|
toteuttaa kuin syvyyshaku.
|
|
|
|
Leveyshakua voi ajatella niin,
|
|
että se käy solmuja läpi kerros kerrallaan.
|
|
Ensin haku käy läpi solmut,
|
|
joihin pääsee yhdellä kaarella
|
|
alkusolmusta.
|
|
Tämän jälkeen vuorossa ovat
|
|
solmut, joihin pääsee kahdella
|
|
kaarella alkusolmusta, jne.
|
|
Sama jatkuu, kunnes uusia käsiteltäviä
|
|
solmuja ei enää ole.
|
|
|
|
\subsubsection*{Esimerkki}
|
|
|
|
Tarkastellaan leveyshaun toimintaa
|
|
seuraavassa verkossa:
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle] (1) at (1,5) {$1$};
|
|
\node[draw, circle] (2) at (3,5) {$2$};
|
|
\node[draw, circle] (3) at (5,5) {$3$};
|
|
\node[draw, circle] (4) at (1,3) {$4$};
|
|
\node[draw, circle] (5) at (3,3) {$5$};
|
|
\node[draw, circle] (6) at (5,3) {$6$};
|
|
|
|
|
|
\path[draw,thick,-] (1) -- (2);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (3) -- (6);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
\path[draw,thick,-] (5) -- (6);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Oletetaan jälleen,
|
|
että haku alkaa solmusta 1.
|
|
Haku etenee ensin kaikkiin solmuihin,
|
|
joihin pääsee alkusolmusta:
|
|
\\
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle,fill=lightgray] (1) at (1,5) {$1$};
|
|
\node[draw, circle,fill=lightgray] (2) at (3,5) {$2$};
|
|
\node[draw, circle] (3) at (5,5) {$3$};
|
|
\node[draw, circle,fill=lightgray] (4) at (1,3) {$4$};
|
|
\node[draw, circle] (5) at (3,3) {$5$};
|
|
\node[draw, circle] (6) at (5,3) {$6$};
|
|
|
|
\path[draw,thick,-] (1) -- (2);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (3) -- (6);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
\path[draw,thick,-] (5) -- (6);
|
|
|
|
\path[draw,thick,-] (1) -- (2);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
|
|
\path[draw=red,thick,->,line width=2pt] (1) -- (2);
|
|
\path[draw=red,thick,->,line width=2pt] (1) -- (4);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Seuraavaksi haku etenee solmuihin 3 ja 5:
|
|
\\
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle,fill=lightgray] (1) at (1,5) {$1$};
|
|
\node[draw, circle,fill=lightgray] (2) at (3,5) {$2$};
|
|
\node[draw, circle,fill=lightgray] (3) at (5,5) {$3$};
|
|
\node[draw, circle,fill=lightgray] (4) at (1,3) {$4$};
|
|
\node[draw, circle,fill=lightgray] (5) at (3,3) {$5$};
|
|
\node[draw, circle] (6) at (5,3) {$6$};
|
|
|
|
\path[draw,thick,-] (1) -- (2);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (3) -- (6);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
\path[draw,thick,-] (5) -- (6);
|
|
|
|
\path[draw,thick,-] (1) -- (2);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
|
|
\path[draw=red,thick,->,line width=2pt] (2) -- (3);
|
|
\path[draw=red,thick,->,line width=2pt] (2) -- (5);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Viimeisenä haku etenee solmuun 6:
|
|
\\
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle,fill=lightgray] (1) at (1,5) {$1$};
|
|
\node[draw, circle,fill=lightgray] (2) at (3,5) {$2$};
|
|
\node[draw, circle,fill=lightgray] (3) at (5,5) {$3$};
|
|
\node[draw, circle,fill=lightgray] (4) at (1,3) {$4$};
|
|
\node[draw, circle,fill=lightgray] (5) at (3,3) {$5$};
|
|
\node[draw, circle,fill=lightgray] (6) at (5,3) {$6$};
|
|
|
|
\path[draw,thick,-] (1) -- (2);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (3) -- (6);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
\path[draw,thick,-] (5) -- (6);
|
|
|
|
\path[draw,thick,-] (1) -- (2);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
|
|
\path[draw=red,thick,->,line width=2pt] (3) -- (6);
|
|
\path[draw=red,thick,->,line width=2pt] (5) -- (6);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Leveyshaun tuloksena selviää etäisyys
|
|
kuhunkin verkon solmuun alkusolmusta.
|
|
Etäisyys on sama kuin kerros,
|
|
jossa solmu käsiteltiin haun aikana:
|
|
|
|
\begin{tabular}{ll}
|
|
\\
|
|
solmu & etäisyys \\
|
|
\hline
|
|
1 & 0 \\
|
|
2 & 1 \\
|
|
3 & 2 \\
|
|
4 & 1 \\
|
|
5 & 2 \\
|
|
6 & 3 \\
|
|
\\
|
|
\end{tabular}
|
|
|
|
Leveyshaun aikavaativuus on syvyyshaun tavoin $O(n+m)$,
|
|
missä $n$ on solmujen määrä ja $m$ on kaarten määrä.
|
|
|
|
\subsubsection*{Toteutus}
|
|
|
|
Leveyshaku on syvyyshakua hankalampi toteuttaa,
|
|
koska haku käy läpi solmuja verkon eri
|
|
puolilta niiden etäisyyden mukaan.
|
|
Tyypillinen toteutus on pitää yllä jonoa
|
|
käsiteltävistä solmuista.
|
|
Joka askeleella otetaan käsittelyyn seuraava
|
|
solmu jonosta ja uudet solmut lisätään
|
|
jonon perälle.
|
|
|
|
Seuraava koodi toteuttaa leveyshaun
|
|
solmusta $x$ lähtien.
|
|
Koodi olettaa, että verkko on tallennettu
|
|
vieruslistoina, ja pitää yllä jonoa
|
|
\begin{lstlisting}
|
|
queue<int> q;
|
|
\end{lstlisting}
|
|
joka sisältää solmut käsittelyjärjestyksessä.
|
|
Koodi lisää aina uudet vastaan tulevat solmut
|
|
jonon perään ja ottaa seuraavaksi käsiteltävän
|
|
solmun jonon alusta,
|
|
minkä ansiosta solmut käsitellään
|
|
kerroksittain alkusolmusta lähtien.
|
|
|
|
Lisäksi koodi käyttää taulukoita
|
|
\begin{lstlisting}
|
|
int z[N], e[N];
|
|
\end{lstlisting}
|
|
niin, että taulukko \texttt{z} sisältää tiedon,
|
|
missä solmuissa haku on käynyt,
|
|
ja taulukkoon \texttt{e} lasketaan lyhin
|
|
etäisyys alkusolmusta kaikkiin verkon solmuihin.
|
|
Toteutuksesta tulee seuraavanlainen:
|
|
\begin{lstlisting}
|
|
z[s] = 1; e[x] = 0;
|
|
q.push(x);
|
|
while (!q.empty()) {
|
|
int s = q.front(); q.pop();
|
|
// solmun s käsittely tähän
|
|
for (auto u : v[s]) {
|
|
if (z[u]) continue;
|
|
z[u] = 1; e[u] = e[s]+1;
|
|
q.push(u);
|
|
}
|
|
}
|
|
\end{lstlisting}
|
|
|
|
\section{Sovelluksia}
|
|
|
|
Verkon läpikäynnin avulla
|
|
saa selville monia asioita
|
|
verkon rakenteesta.
|
|
Läpikäynnin voi yleensä aina toteuttaa
|
|
joko syvyyshaulla tai leveyshaulla,
|
|
mutta käytännössä syvyyshaku on parempi valinta,
|
|
koska sen toteutus on helpompi.
|
|
Oletamme seuraavaksi, että käsiteltävänä on
|
|
suuntaamaton verkko.
|
|
|
|
\subsubsection{Yhtenäisyyden tarkastaminen}
|
|
|
|
\index{yhtenxisyys@yhtenäisyys}
|
|
|
|
Verkko on yhtenäinen,
|
|
jos mistä tahansa solmuista
|
|
pääsee kaikkiin muihin solmuihin.
|
|
Niinpä verkon yhtenäisyys selviää
|
|
aloittamalla läpikäynti
|
|
jostakin verkon solmusta ja
|
|
tarkastamalla, pääseekö siitä kaikkiin solmuihin.
|
|
|
|
Esimerkiksi verkossa
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle] (2) at (7,5) {$2$};
|
|
\node[draw, circle] (1) at (3,5) {$1$};
|
|
\node[draw, circle] (3) at (5,4) {$3$};
|
|
\node[draw, circle] (5) at (7,3) {$5$};
|
|
\node[draw, circle] (4) at (3,3) {$4$};
|
|
|
|
\path[draw,thick,-] (1) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (3) -- (4);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
solmusta $1$ alkava syvyyshaku löytää seuraavat
|
|
solmut:
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle] (2) at (7,5) {$2$};
|
|
\node[draw, circle,fill=lightgray] (1) at (3,5) {$1$};
|
|
\node[draw, circle,fill=lightgray] (3) at (5,4) {$3$};
|
|
\node[draw, circle] (5) at (7,3) {$5$};
|
|
\node[draw, circle,fill=lightgray] (4) at (3,3) {$4$};
|
|
|
|
\path[draw,thick,-] (1) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (3) -- (4);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
|
|
\path[draw=red,thick,->,line width=2pt] (1) -- (3);
|
|
\path[draw=red,thick,->,line width=2pt] (3) -- (4);
|
|
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
Koska syvyyshaku ei pääse kaikkiin solmuihin,
|
|
tämä tarkoittaa, että verkko ei ole yhtenäinen.
|
|
Vastaavalla tavalla voi etsiä myös verkon komponentit
|
|
käymällä solmut läpi ja aloittamalla uuden syvyyshaun
|
|
aina, jos käsiteltävä solmu ei kuulu vielä mihinkään komponenttiin.
|
|
|
|
\subsubsection{Syklin etsiminen}
|
|
|
|
\index{sykli@sykli}
|
|
|
|
Verkossa on sykli,
|
|
jos jonkin komponentin läpikäynnin
|
|
aikana tulee vastaan solmu,
|
|
jonka naapuri on jo käsitelty
|
|
ja solmuun ei ole saavuttu kyseisen naapurin kautta.
|
|
Esimerkiksi verkossa
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle,fill=lightgray] (2) at (7,5) {$2$};
|
|
\node[draw, circle,fill=lightgray] (1) at (3,5) {$1$};
|
|
\node[draw, circle,fill=lightgray] (3) at (5,4) {$3$};
|
|
\node[draw, circle,fill=lightgray] (5) at (7,3) {$5$};
|
|
\node[draw, circle] (4) at (3,3) {$4$};
|
|
|
|
\path[draw,thick,-] (1) -- (3);
|
|
\path[draw,thick,-] (1) -- (4);
|
|
\path[draw,thick,-] (3) -- (4);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (3) -- (5);
|
|
|
|
\path[draw=red,thick,->,line width=2pt] (1) -- (3);
|
|
\path[draw=red,thick,->,line width=2pt] (3) -- (2);
|
|
\path[draw=red,thick,->,line width=2pt] (2) -- (5);
|
|
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
on sykli, koska tultaessa solmusta 2 solmuun 5
|
|
havaitaan, että naapurina oleva solmu 3 on jo käsitelty.
|
|
Niinpä verkossa täytyy olla solmun 3 kautta
|
|
kulkeva sykli.
|
|
Tällainen sykli on esimerkiksi
|
|
$3 \rightarrow 2 \rightarrow 5 \rightarrow 3$.
|
|
|
|
Syklin olemassaolon voi myös päätellä laskemalla,
|
|
montako solmua ja kaarta komponentissa on.
|
|
Jos komponentissa on $c$ solmua ja siinä ei ole sykliä,
|
|
niin siinä on oltava tarkalleen $c-1$ kaarta.
|
|
Jos kaaria on $c$ tai enemmän, niin komponentissa
|
|
on varmasti sykli.
|
|
|
|
\subsubsection{Kaksijakoisuuden tarkastaminen}
|
|
|
|
\index{kaksijakoisuus@kaksijakoisuus}
|
|
|
|
Verkko on kaksijakoinen,
|
|
jos sen solmut voi värittää
|
|
kahdella värillä
|
|
niin, että kahta samanväristä
|
|
solmua ei ole vierekkäin.
|
|
On yllättävän helppoa selvittää
|
|
verkon läpikäynnin avulla,
|
|
onko verkko kaksijakoinen.
|
|
|
|
Ideana on värittää alkusolmu
|
|
siniseksi, sen kaikki naapurit
|
|
punaiseksi, niiden kaikki naapurit
|
|
siniseksi, jne.
|
|
Jos jossain vaiheessa
|
|
ilmenee ristiriita
|
|
(saman solmun tulisi olla sekä
|
|
sininen että punainen),
|
|
verkko ei ole kaksijakoinen.
|
|
Muuten verkko on kaksijakoinen
|
|
ja yksi väritys on muodostunut.
|
|
|
|
Esimerkiksi verkko
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle] (2) at (5,5) {$2$};
|
|
\node[draw, circle] (1) at (3,5) {$1$};
|
|
\node[draw, circle] (3) at (7,4) {$3$};
|
|
\node[draw, circle] (5) at (5,3) {$5$};
|
|
\node[draw, circle] (4) at (3,3) {$4$};
|
|
|
|
\path[draw,thick,-] (1) -- (2);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
\path[draw,thick,-] (5) -- (4);
|
|
\path[draw,thick,-] (4) -- (1);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (5) -- (3);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
ei ole kaksijakoinen, koska
|
|
läpikäynti solmusta 1 alkaen
|
|
aiheuttaa seuraavan ristiriidan:
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\node[draw, circle,fill=red!40] (2) at (5,5) {$2$};
|
|
\node[draw, circle,fill=blue!40] (1) at (3,5) {$1$};
|
|
\node[draw, circle,fill=blue!40] (3) at (7,4) {$3$};
|
|
\node[draw, circle,fill=red!40] (5) at (5,3) {$5$};
|
|
\node[draw, circle] (4) at (3,3) {$4$};
|
|
|
|
\path[draw,thick,-] (1) -- (2);
|
|
\path[draw,thick,-] (2) -- (5);
|
|
\path[draw,thick,-] (5) -- (4);
|
|
\path[draw,thick,-] (4) -- (1);
|
|
\path[draw,thick,-] (2) -- (3);
|
|
\path[draw,thick,-] (5) -- (3);
|
|
|
|
\path[draw=red,thick,->,line width=2pt] (1) -- (2);
|
|
\path[draw=red,thick,->,line width=2pt] (2) -- (3);
|
|
\path[draw=red,thick,->,line width=2pt] (3) -- (5);
|
|
\path[draw=red,thick,->,line width=2pt] (5) -- (2);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
Tässä vaiheessa havaitaan,
|
|
että sekä solmun 2 että solmun 5 väri on punainen,
|
|
vaikka solmut ovat vierekkäin verkossa,
|
|
joten verkko ei ole kaksijakoinen.
|
|
|
|
Tämä algoritmi on luotettava tapa selvittää
|
|
verkon kaksijakoisuus,
|
|
koska kun värejä on vain kaksi,
|
|
ensimmäisen solmun värin valinta
|
|
määrittää kaikkien muiden
|
|
samassa komponentissa olevien
|
|
solmujen värin.
|
|
Ei ole merkitystä,
|
|
kumman värin ensimmäinen
|
|
solmu saa.
|
|
|
|
Huomaa, että yleensä ottaen on vaikeaa
|
|
selvittää, voiko verkon solmut
|
|
värittää $k$ värillä niin,
|
|
ettei missään kohtaa ole vierekkäin
|
|
kahta samanväristä solmua.
|
|
Edes tapaukseen $k=3$ ei tunneta
|
|
mitään tehokasta algoritmia,
|
|
vaan kyseessä on NP-vaikea ongelma.
|
|
%
|
|
% \section{Labyrintin käsittely}
|
|
%
|
|
% Labyrintti on ruudukko, joka muodostuu lattia- ja seinäruuduista,
|
|
% ja labyrintissa on sallittua kulkea lattiaruutuja pitkin.
|
|
% Labyrinttia
|
|
% \begin{center}
|
|
% \begin{tikzpicture}[scale=0.7]
|
|
% \fill[color=gray] (0,0) rectangle (8,1);
|
|
% \fill[color=gray] (0,5) rectangle (8,6);
|
|
% \fill[color=gray] (0,0) rectangle (1,6);
|
|
% \fill[color=gray] (7,0) rectangle (8,6);
|
|
%
|
|
% \fill[color=gray] (2,0) rectangle (3,4);
|
|
% \fill[color=gray] (4,2) rectangle (6,4);
|
|
%
|
|
% \draw (0,0) grid (8,6);
|
|
%
|
|
% \node at (1.5,1.5) {$a$};
|
|
% \node at (6.5,3.5) {$b$};
|
|
% \end{tikzpicture}
|
|
% \end{center}
|
|
% vastaa luontevasti verkko
|
|
% \begin{center}
|
|
% \begin{tikzpicture}[scale=0.7]
|
|
% \node[draw,circle,minimum size=20pt] (a) at (1,1) {$a$};
|
|
% \node[draw,circle,minimum size=20pt] (b) at (1,2.5) {};
|
|
% \node[draw,circle,minimum size=20pt] (c) at (1,4) {};
|
|
% \node[draw,circle,minimum size=20pt] (d) at (1,5.5) {};
|
|
% \node[draw,circle,minimum size=20pt] (e) at (2.5,5.5) {};
|
|
% \node[draw,circle,minimum size=20pt] (f) at (4,5.5) {};
|
|
% \node[draw,circle,minimum size=20pt] (g) at (5.5,5.5) {};
|
|
% \node[draw,circle,minimum size=20pt] (h) at (7,5.5) {};
|
|
% \node[draw,circle,minimum size=20pt] (i) at (8.5,5.5) {};
|
|
% \node[draw,circle,minimum size=20pt] (j) at (8.5,4) {$b$};
|
|
% \node[draw,circle,minimum size=20pt] (k) at (8.5,2.5) {};
|
|
% \node[draw,circle,minimum size=20pt] (l) at (8.5,1) {};
|
|
% \node[draw,circle,minimum size=20pt] (m) at (7,1) {};
|
|
% \node[draw,circle,minimum size=20pt] (n) at (5.5,1) {};
|
|
% \node[draw,circle,minimum size=20pt] (o) at (4,1) {};
|
|
% \node[draw,circle,minimum size=20pt] (p) at (4,2.5) {};
|
|
% \node[draw,circle,minimum size=20pt] (q) at (4,4) {};
|
|
%
|
|
% \path[draw,thick,-] (a) -- (b);
|
|
% \path[draw,thick,-] (b) -- (c);
|
|
% \path[draw,thick,-] (c) -- (d);
|
|
% \path[draw,thick,-] (d) -- (e);
|
|
% \path[draw,thick,-] (e) -- (f);
|
|
% \path[draw,thick,-] (f) -- (g);
|
|
% \path[draw,thick,-] (g) -- (h);
|
|
% \path[draw,thick,-] (h) -- (i);
|
|
% \path[draw,thick,-] (i) -- (j);
|
|
% \path[draw,thick,-] (j) -- (k);
|
|
% \path[draw,thick,-] (k) -- (l);
|
|
% \path[draw,thick,-] (l) -- (m);
|
|
% \path[draw,thick,-] (m) -- (n);
|
|
% \path[draw,thick,-] (n) -- (o);
|
|
% \path[draw,thick,-] (o) -- (p);
|
|
% \path[draw,thick,-] (p) -- (q);
|
|
% \path[draw,thick,-] (q) -- (f);
|
|
% \end{tikzpicture}
|
|
% \end{center}
|
|
% jossa verkon solmuja ovat labyrintin lattiaruudut
|
|
% ja solmujen välillä on kaari, jos lattiaruudusta
|
|
% toiseen pääsee kulkemaan yhdellä askeleella.
|
|
% Niinpä erilaiset labyrinttiin liittyvät ongelmat
|
|
% palautuvat verkko-ongelmiksi.
|
|
%
|
|
% Esimerkiksi syvyyshaulla pystyy selvittämään,
|
|
% onko ruudusta $a$ reittiä ruutuun $b$
|
|
% ja leveyshaku kertoo lisäksi,
|
|
% mikä on pienin mahdollinen askelten määrä reitillä.
|
|
% Samoin voi esimerkiksi vaikkapa, kuinka monta
|
|
% toisistaan erillistä huonetta labyrintissa on
|
|
% sekä kuinka monta ruutua huoneissa on.
|
|
%
|
|
% Labyrintin tapauksessa ei kannata muodostaa erikseen
|
|
% verkkoa, vaan syvyyshaun ja leveyshaun voi toteuttaa
|
|
% suoraan labyrintin ruudukkoon.
|
|
|