21
Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1. Dijkstra algoritmusa Hujter Bálint Specmat továbbképzés, 2015. július 1. Az alábbi képeken 1 Franciország úthálózatának sematikus rajza látható. Többféle útvonal szóba jöhet két város, például Párizs és Marseille között. Természetes kérdés, hogy miként lehet ezek közül a legrövidebbet kiválasztani, összhosszúságát meghatározni. Dijkstra algoritmusa erre, és ehhez hasonló feladatok egy nagyobb családjának megoldására ad gyakorlatban is jól használható módszert. Több érv is felhozható a speciális matematika szakon való tanítása mellett. A megoldandó feladat egy természetes és valószerű probléma (gon- doljunk az útvonaltervező szoftverekre). Az ismertetendő algoritmu ténylegesen jól használható a valóságközeli problémáknál – a legjobb szoftverek is tipikusan ennek néhány ügyes trükkel módosított verzióit használják. A Dijkstra-algoritmus ráadásul algoritmus egyáltalán nem bo- nyolult, egy diák akár magától is rájöhet. Mégis több messzire vezető, például adatstruktúrákal kapcsolatos kérdés is természetesen vetődik fel a méylebb vizsgálata során. A hazai és nemzetközi programozó versenyeken is rendszeresen szerepelnek a Dijkstra- algoritmushoz kapcsolódó feladatok. Jó, ha a diákok látják, hogy ez nem csak egy infom- ratikai eszköz, hanem értelmes és érdekes matematikai háttere van – ennek mélyebb megértése programozóként is segítheti őket. Előzetes tudás Előzetes tudásként támaszkodunk némi gráfelméleti alapiseretre (utak, séták, szélességi bejá- rás, irányított élek). Nem feltétel, de hasznos, ha a diákok programozni is tudnak; különösen is jó, ha gráfalgoritmusokat is kódoltak már. Érdemes az algoritmus lépésszámáról részletesen beszélni, ehhez némi algoritmuselméleti elő- képzettség is szükséges lehet (maximumkeresés összehasonlításokkal – bináris keresés, aritme- tikai műveletek algoritmizálása). 1 forrás: http://www.bonjourlafrance.com/france-map/images/france-driving-distances.jpg 1

Dijkstra algoritmusa - ELTEweb.cs.elte.hu/~jpet/specmat/dijkstra_hujterb.pdfFontos a diákokkal megbeszélni, hogy a Dijkstra-algoritmus érdemi változtatás nélkül működik irányított

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    Dijkstra algoritmusaHujter Bálint

    Specmat továbbképzés, 2015. július 1.

    Az alábbi képeken1 Franciország úthálózatának sematikus rajza látható. Többféle útvonalszóba jöhet két város, például Párizs és Marseille között. Természetes kérdés, hogy miként lehetezek közül a legrövidebbet kiválasztani, összhosszúságát meghatározni.

    Dijkstra algoritmusa erre, és ehhez hasonló feladatok egy nagyobb családjának megoldásáraad gyakorlatban is jól használható módszert. Több érv is felhozható a speciális matematikaszakon való tanítása mellett. A megoldandó feladat egy természetes és valószerű probléma (gon-doljunk az útvonaltervező szoftverekre). Az ismertetendő algoritmu ténylegesen jól használhatóa valóságközeli problémáknál – a legjobb szoftverek is tipikusan ennek néhány ügyes trükkelmódosított verzióit használják. A Dijkstra-algoritmus ráadásul algoritmus egyáltalán nem bo-nyolult, egy diák akár magától is rájöhet. Mégis több messzire vezető, például adatstruktúrákalkapcsolatos kérdés is természetesen vetődik fel a méylebb vizsgálata során.

    A hazai és nemzetközi programozó versenyeken is rendszeresen szerepelnek a Dijkstra-algoritmushoz kapcsolódó feladatok. Jó, ha a diákok látják, hogy ez nem csak egy infom-ratikai eszköz, hanem értelmes és érdekes matematikai háttere van – ennek mélyebb megértéseprogramozóként is segítheti őket.

    Előzetes tudás

    Előzetes tudásként támaszkodunk némi gráfelméleti alapiseretre (utak, séták, szélességi bejá-rás, irányított élek). Nem feltétel, de hasznos, ha a diákok programozni is tudnak; különösenis jó, ha gráfalgoritmusokat is kódoltak már.Érdemes az algoritmus lépésszámáról részletesen beszélni, ehhez némi algoritmuselméleti elő-képzettség is szükséges lehet (maximumkeresés összehasonlításokkal – bináris keresés, aritme-tikai műveletek algoritmizálása).

    1forrás: http://www.bonjourlafrance.com/france-map/images/france-driving-distances.jpg

    1

    http://www.bonjourlafrance.com/france-map/images/france-driving-distances.jpg

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    1. Legrövidebb utak

    s v1

    v2

    v3v4

    v5

    v6 v7

    t

    1.1. feladat. Hány élből áll a legrövidebb út az alábbigráfon s és t csúcsok között?

    1.1. megjegyzés. Az s és t betűjelekkel az angol source(forrás, kezdőpont) és target (célpont) elnevezésekre uta-lunk.

    Megoldás. A kérdésre könnyen megkapjuk a választ szélességi bejárással, egy legrövidebb út 4élből áll. A legrövidebb utak szerkezete is jól látszik: éppen akkor lesz egy st-út 4 hosszú (azazlegrövedebb), ha minden éle egyet lefele lépő él a szélességi fában.

    0(s) 1

    2

    31

    2

    2 3

    4(t)

    s

    v1

    v2

    v3

    v4

    v5 v6

    v7

    t

    Hogyan változik a helyzet, ha különböző élek igénybevétele különböző költséggel járhat? (Aköltség többféle jellegű lehet: távolság, idő, pénz.)

    1.2. feladat. Az ábra egy park ösvényeinek vázlatos rajza. Minden útszakaszra felírtuk, hogyhány percig tart rajta végigsétálni. Legkevesebb hány percig tart egy s-ból t-be menő séta?(Hogyan járnánk el egy hasonló, de több csúcsú és élű gráf esetén?)

    s v1

    v2

    v3v4

    v5

    v6 v7

    t

    6

    5

    57

    5

    4

    6 34

    2

    3

    2

    2

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    Jó ötletnek tűnhet ismét a szélességi kereséssel próbálkozni. Ha a szélességi keresés sor-rendjében próbálnánk kiszámolni ki az egyes csúcsok távolságát a szomszédaik távolságánaksegítségével, a bal oldali ábrán látható távolságokat kapnánk.

    Ezzel szemben a jobb oldali ábra mutat egy rövidebb összegű utat, mint amit az előbbmegtaláltunk.

    0s 6[1]

    11[2]

    16[3]5[1]

    9[2]

    13[2] 15[3]

    17[4]

    6

    57

    5

    4

    6 3

    5

    4

    2

    3

    2

    s v1

    v2

    v3v4

    v5

    v6 v7

    t

    6

    57

    5

    4

    6 3

    5

    4

    2

    3

    2

    Ezzel a módszerrel több probléma is fellép. Ha a legrövidebb út nem minimálisan sok élbőláll (ld. a fenti példát), akkor ilyen módon nem fogjuk megtalálni. Ha több, ugyanannyi élbőlálló út megy két csúcs között, akkor sem világos, hogy hogyan válasszuk ki a legjobbat (ha pl.v7-ből v1-be szeretnénk menni.)

    Megpróbálhatjuk a feladatot visszavezetni a súlyozatlan gráfok esetére is, ahol már bizton-ságosan működik a szélességi keresés. Cseréljünk ki minden élt egy az élsúlyának megfelelőszámú (súlyozatlan) élből álló útra. Ezt a változtatást mutatja be egy egyszerűbb gráfon akövetkező ábrapár.

    3

    42

    Az így módosított gráfon már tudjuk futtatni a jól bevált szélességi keresést. Világos, hogya módosított gráfban kapott legrövidebb (legkevesebb élből) álló út megfelel az eredeti gráf egyminimális összhosszúságú útjának.

    2. Dijkstra algoritmusaAz általános esetben a következő feladatot szeretnénk megoldani.

    2.1. feladat. Adott egy G = (V,E) gráf és az élein egy ` : E → R+ hosszúságfüggvény. Adotts, t ∈ V csúcsokra keressük a minimális összhosszúságú st utat.

    3

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    Megpróbáljuk az előző ötletünket használni, minden e élt cseréljünk ki egy `(e) darab élbőlálló útra. A felosztott gráfon (jelölje G′) futtassunk szélességi keresést.

    Módszerünknek vannak korlátai. Bajban vagyunk például, ha az `(e) értékek nem egészek.Amennyiben az értékek még racionálisak, felszorozva a nevezők legkisebb közös többszörösével,ez a gond még orvosolható. (Az irracionális számok esete azért így is megmarad, bár ez agyakorlati alkalmazásokban nem jelent problémát, mivel a életből vett hosszúságadatok sosemlesznek irracionális számok.)

    Nehezebben feloldható problémát jelent, ha az `(e) értékek között vannak nagy számok(például a közös nevezővel való felszorzás könnyen eredményezhet ilyet). Ilyen módon a gráfélszáma, ezzel pedig algoritmusunk lépésszáma megsokszorozódik; így a feladat gyakorlati szem-pontból könnyen kezelhetetlenné válhat. Erről részletesebben a 4.4 megjegyzésben írunk majd.

    Dijkstra algoritmusa (1956) elegánsan kerüli ki ezt a prob-lémát. Az algoritmus úgy is felfogható, hogy a G′-n futtatottszélességi keresést modellezzük, anélkül hogy az élek felosztá-sakor keletkező extra csúcsokkal egyenként foglalkoznánk. ADijkstra-algoritmusban abban a sorrendben fogjuk átvizsgálnia G gráf csúcsait, ahogyan a G′-n futtatott szélességi keresés-ben sorra kerülnének a nekik megfelelő csúcsok.Ha nem akarunk a felosztott G′ gráfra gondolni, akkor tekint-hetjük úgy is, hogy az eredeti G-n folytatunk egy a kövektezőelvek mentén módosított szélességi keresést:

    • Az átvizsgálásra soron következő csúcs kiválasztásánálkörültekintőbben járunk el.

    • Egy elért (de még nem átvizsgált) csúcsnál fenntartjukannak a lehetőségét, hogy később rövidebb odavezetőutat találjunk.

    Edsger W. Dijkstra(1930-2002)

    2.1. megjegyzés. Edsger W. Dijkstra holland tudós volt, a holland nevek kiejtése pedig nemmagától értetődő. Akit érdekel az eredeti kiejtés, itt meghallgathatja: https://en.wikipedia.org/wiki/File:Dijkstra.ogg.

    2.1. A Dijkstra-algoritmus részletes ismertetése

    Tárolandó adatok: Az algoritmus futás egy köztes pillanatát a csúcsok állapotai és a csúcsok-hoz tartozó bizonyos paraméterek értékei határozzák meg (a futás során mind a csúcs-állapotok,mind a paraméterek dinamikusan változnak).A csúcsok az alábbi állapotokban lehetnek:

    x L: Lezárty

    N: Nem lezárt (elért) z N: Nem lezárt (nem elért)

    A nem lezárt csúcsok között vannak már elértek és még nem elértek, de az ezek közöttikülönbségtétel az algoritmus megértésében segít, a helyes futtatáshoz valójában nem szükséges.Elég csak azt tárolni, hogy a csúcsok L vagy N állapotban vannak.

    Egy már elért v csúcs mellett mindig tárolunk egy hozzá tartozó d(v) értéket is, melynekjelentése az eddig megtalált legrövidebb sv út hossza.

    4

    https://en.wikipedia.org/wiki/File:Dijkstra.ogghttps://en.wikipedia.org/wiki/File:Dijkstra.ogg

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    Praktikus a már elért csúcsok mellett az ún. szülőjük azonosítóját is tárolni.

    Kezdeti állapot: Kezdetben minden csúcs N állapotban van, d(s) = 0, a többi csúcsnakpedig még nincs d(v) értéke (tekinthető úgy, hogy d(v) =∞).

    Az algoritmus egy lépése: Az N állapotúak közül kiválasztjuk azt az u csúcsot, amire d(u)minimális (ha több ilyen is van, akkor tetszőlegesen választunk ezek közül egyet). Minden uvélre megvizsgáljuk a d(v) értékeket. Ha még nincs d(v) érték vagy d(u) + `(u, v) < d(v), akkord(v) új értéke d(u) + `(u, v) lesz, továbbá v szülője u lesz. Ezután az uv élt töröljük a gráfból.Ha már nincs uv′ él, akkor u állapotát L-re változtatjuk és a következő lépésre ugrunk.

    Az algoritmust addig folytatjuk, amíg t csúcs L állapotú nem lesz. Nem összefüggő gráfesetén az is előfordulhat, hogy az N állapotú csúcsok egyikének sincs (∞-től különböző) d(v)értéke, ilyenkor is megállunk. d(t) leálláskori értéke adja meg a legrövidebb st út hosszát.

    2.2. megjegyzés. Ha a Dijkstra algoritmust addig futtatjuk, amíg az összes elérhető csúcs L álla-potú lesz, akkor valójában nem csak t-re, hanem az összes s-ből elérhető v csúcsra meghatározzaa legrövidebb sv út hosszát.

    2.2. Az algoritmus futása egy konkrét gráfon

    1. fázis

    s v1

    v4

    v2

    v3

    v5

    v6 v7

    t

    57

    5

    4

    6 34

    2

    3

    2

    6

    5

    csúcs d(v) szülő lezárva?s 0 - Lv1 6 s Nv4 5 s N

    2. fázis

    s

    v4

    v1

    v5

    v3

    v2

    v6 v7

    t

    57

    5

    4

    6 3

    2

    3

    2

    6

    5

    4csúcs d(v) szülő lezárva?s 0 - Lv4 5 s Lv1 6 s Nv5 9 v4 N

    5

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    3. fázis

    s v1

    v4

    v2

    v5

    v6

    v3

    v7

    t5

    4

    6 3

    2

    3

    2

    6

    5

    4

    57

    csúcs d(v) szülő lezárva?s 0 - Lv1 6 s Lv4 5 s Lv2 11 v1 Nv5 9 v4 Nv6 13 v1 N

    4. fázis

    Most jön az érdekes lépés!

    s v1

    v4

    v5

    v2

    v6

    v3

    v7

    t5

    4

    3

    3

    2

    6

    5

    4

    57

    6

    2

    csúcs d(v) szülő lezárva?s 0 - Lv1 6 s Lv4 5 s Lv5 9 v4 Lv2 11 * v1 Nv3 15 v5 Nv6 11 v5 N

    *Holtverseny esetén választhatunk

    pl. lexikografikus sorrend szerint.

    Újabb fázisok

    Az 5-8. fázisok részletes rekonstruálását az olvasóra bízzuk. Az 5. fázisban a v2; a 6. fázisbana v6; a 7. fázisban a v7 csúcs, míg végül a 8. fázisban a v3 csúcs is átvizsgálásra, majd lezárásrakerül. Érdemes még megjegyezni, hogy így a v7-et előbb v2-ből érjük majd el (15 távolság), ésez a következő fázisban kerül majd csak átírásra.

    Végállapot

    Végül a 8. fázisban megállapítjuk, hogy t minden éle át lett már vizsgálva korábban, t-t ígylezárhatjuk, és leolvashatjuk a végeredményt.

    6

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    s v1

    v2

    v3v4

    v5

    v6 v7

    t5

    4

    3

    3

    2

    6

    5

    4

    57

    6

    2

    v d(v) szülő lezárva?s 0 - Lv1 6 s Lv2 11 v1 Lv3 15 v4 Lv4 5 s Lv5 9 v4 Lv6 11 v5 Lv7 14 v6 Lt 16 v7 L

    2.3. megjegyzés. A Dijkstra-algoritmus egy látványos szimulációja érhető el az alábbi címen:https://www.cs.usfca.edu/~galles/visualization/Dijkstra.html

    2.4. megjegyzés. Vegyük észre, hogy amennyiben nem állunk meg t átvizsgálásakor, hanem addigfuttatjuk az algoritmust, amíg az összes csúcs lezárt nem lesz, akkor t semmilyen kitüntetettszerepet nem játszik.

    2.3. Az algoritmus helyességének igazolása

    Az algoritmust részletesen bemutattuk. Következő feladatunk, hogy igazoljuk, hogy valóban alegrövidebb st út hosszát adja tetszőleges G = (V,E) gráf és ` : V → R+ hosszfüggvény esetén.Ezt érdemes önálló feladatként is feladni diákjainknak:

    2.2. feladat. Igazoljuk, hogy a Dijkstra-algoritmus megadja a legrövidebb st út hosszát; tetsző-leges G = (V,E) gráf és ` : V → R+ hosszfüggvény esetén.

    Az algoritmus helyessége a következő, teljes indukcióval igazolható állításon múlik:

    2.5. állítás. (Az algoritmus futásának tetszőleges köztes állapotában igaz, hogy:) Minden Lállapotú u csúcsra d(u) a legrövidebb su út hossza. Az N állapotú v csúcsokra d(v) értéke (halétezik) a legrövidebb olyan út hossza, ami csupa L állapotú csúcsokon át halad s-ből v-be.

    Bizonyítás. Az lezárt csúcsok száma szerinti teljes indukcióval bizonyítunk. Kezdetben (amikorcsak s lezárt) az állítás triviális.Tegyük fel, hogy n−1 lezárt csúcs esetén még igaz volt; belátjuk,hogy ez az n. csúcs lezárásával is megmarad.

    Az n. lezárt csúcs egy olyan v lesz, amelyhez van egy olyan uv él, ahol u ∈ L és v ∈N , továbbá d(v) = d(u) + `(u, v) minimális az ilyen csúcspárok között. Ekkor a v-be menőlegrövidebb sv út d(v) hosszú kell legyen; hiszen ha lenne egy rövidebb P ′ sv-út, ennek az elsőN állapotú csúcsára d(w) < d(v) kellene, hogy teljesüljön, ellentmondva a v választásának.

    v átvizsgálása után igaz marad az is, hogy minden w ∈ N csúcsra d(w) a legrövidebb csakL-beli csúcsokat használó út. Valóban: ha a legrövidebb ilyen sw út nem használja v-t, akkormár korábban megtaláltuk, ha pedig használja v-t, akkor most kellett megtalálnunk.

    2.4. A legrövidebb utak kiolvasása

    Bemelegítésként érdemes meggondolni a következő feladatot:

    7

    https://www.cs.usfca.edu/~galles/visualization/Dijkstra.html

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    2.3. feladat. Legyen P = (s, v1, . . . , vk, t) egy minimális összhosszúságú st-út. Bizonyítsuk be,hogy ekkor minden 1 ≤ i ≤ k esetén Pi = (s, v1, . . . , vi) is egy minimális összhosszúságú svi-út.

    Megoldás. Indirekt bizonyítunk. Ha lenne vi-be egy rövidebb P ′i út, akkor P ′i -hez a (vi, vi+1, . . . , vk)szakaszt csatolva egy P -nél rövidebb sétát kapnánk. Ha ez a séta esetleg nem út (lehet bennecsúcsismétlés, ezáltal kör), akkor a köröket kivágva belőle egy még rövidebb utat kapunk.

    A következő feladat ad választ arra, hogy miért volt érdemes a szülőt is tárolni az elért csúcsokmellett.

    2.4. feladat. Adjuk meg egy legrövidebb st-út éleit a Dijkstra-algoritmus végallapotánál láthatótáblázat segítségével.

    Megoldás. A keresett utat t-ből visszafele haladva könnyű megtalálni: vegyük t szülőjét, majdannak a szülőjét, stb. Így véges sok lépésben eljutunk s-hez, mivel s kivételével minden lezártcsúcsnak van szülője, egy korábban lezárt csúcs személyében. Így előbb-utóbb a legelőszörlezárt s-hez jutunk, ráadásul kör sem keletkezhetett.

    Legyenek az így kapott út csúcsai sorrendben s, u1, u2, . . . , uk, t. Könnyen látható i szerintiindukcióval, hogy az (s, u1, . . . , ui) egy legrövidebb sui-út.

    s v1

    v2

    v3v4

    v5

    v6 v7

    t

    4

    3

    7

    5

    6

    5

    4

    2

    3

    2

    5

    6

    v d(v) szülő lezárva?s 0 - Lv1 6 s Lv2 11 v1 Lv3 15 v5 Lv4 5 s Lv5 9 v4 Lv6 11 v5 Lv7 14 v6 Lt 16 v7 L

    Valójában nem csak s-ből t-be találjuk meg a legrövidebb utakat így, hanem s-ből az összestöbbi csúcsba is.

    2.5. feladat. Legyen G = (V,E) összefüggő gráf, élein ` : E → R+ egy hosszfüggvény éss ∈ V egy kijelölt csúcs. Futtassuk le a Dijkstra-algoritmust s kezdőpontból, amíg az összescsúcs lezárt állapotú lesz. Minden v csúcsra húzzuk be pirossal az uv irányított élt, ahol u a vcsúcs Dijkstra-algoritmus eredményeként kapott szülője. Bizonyítsuk be a következőket:

    (a) A piros élek egy s-gyökerű ki-fenyőt alkotnak. s-ből bármelyik másik csúcsba egyértelműenlehet eljutni az (irányított) piros éleken.

    (b) Minden v ∈ V -re a piros élek által megadott sv út egy legrövidebb G-beli sv út.

    Megoldás. (a) Minden s-től különböző csúcsba pontosan 1 piros él fut be (s-be pedig egy sem).Így a piros élek száma pontosan n − 1 (ahol n = |V |). Lássuk be, hogy a piros élek nemalkotnak kört (irányítatlan értelemben sem). Egyfelé irányított kör nem lehet, hiszen egy pirosél fejénél nagyobb d(v) érték van, mint a tövénél (másképp: a töve hamarabb lett lezárva aDijkstra-algoritmusban, mint a feje). Ha pedig egy piros körön lenne két ellentétes körüljárásiirányba mutató él, akkor lenne olyan csúcs, amibe két piros él fut be.

    8

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    Körmentes, n-1 élű gráf irányított értelemben fa. Minden irányítás rajta s-től távolodóirányba mutat.

    (b) Az algoritmus helyessége c. szakaszban igazából ezt is beláttuk (hiszen t semmilyenkitüntetett szerepet nem játszott.

    2.5. A Dijkstra-algoritmus fizikai modellje

    2.6. feladat. Egy asztalon gyöngyök fekszenek, ezeket változatos hosszúságú madzagokkal kötjükössze. Így egy gráfszerű hálózatot kapunk. Fogjuk meg az egyik gyöngyöt és függőlegesen emeljükfel az asztalról. Milyen sorrendben fog a többi gyöngy elemelkedni az asztalról?

    Válasz. A gyöngyök abban a sorrendben emelkednek el, mint amilyen sorrendben a megfelelőgráfban a Dijkstra-algoritmus átvizsgálja a csúcsokat.

    3. Irányított gráfok. Gráfok és feladatok megadási módjai3.1. feladat. A következő táblázat a Bergengócia városai között közlekedő repülőgépjáratok jegy-árait tartalmazza. Legkevesebb hány tallérból lehet eljutni Elemérhalomból Cecíliavásárhelyre?

    A B C D E F G H IArtúrbánya - 37 - 28 - 70 - 22 -Bélavár 21 - 32 84 19 31 - 20 65Cecíliavásárhely 42 66 - - - 82 32 - 21Dénesville - 28 32 - - 21 32 89 61Elemérhalom 12 - 97 26 - - 72 34 83Ferencváros 54 - 29 94 35 - - - 64Gizellarév - 63 31 92 - 51 - 75 19Hugófalva 31 21 42 - - 23 61 - 69Ilonahegy 77 - 21 64 - 83 26 - -

    A feladatban a költségek nem szimmetrikusak, azaz X-ből Y -ba tipikusan nem ugyanannyi-ba kerül eljutni, mint Y -ból X-be. Tehát a feladatot egy irányított gráffal tudjuk modellezni.Fontos a diákokkal megbeszélni, hogy a Dijkstra-algoritmus érdemi változtatás nélkülműködik irányított gráfokra. Az algoritmus lépései és a helyességre adott bizonyítás isszóról-szóra megismételhető. Ez tehát semmiféle problémát nem jelent.

    Másrészt, az előző feladat példát mutat a gráfok tárolásánake egyik tipikus módjára, az ún.adjacencia-mátrix ra is. Ennek előnye a jó áttekinthetőség: egy adott csúcs szomszédai könnyenkiolvashatók.

    Az adjacencia-mátrixnál szokványosabb mód egy gráf megadására az éllistás felsorolás. Erreis mutatunk egy példát:

    9

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    0 1 71 2 22 1 31 3 73 4 40 2 54 2 31 4 44 5 53 5 82 4 8

    0

    1

    2

    3

    4

    5

    7

    5

    7

    4 4

    5

    8

    23

    83

    3.1. megjegyzés. Amennyiben gráfunk ritka, azaz csúcsszámához képest kevés éle van, akkor azéllistával jóval kisebb tárhely elég. n csúcsú ésm élű gráf esetén az adjacencia-mátrixban durvánn2 adatot kell eltárolnunk. Éllistával csakm adatsorunk van, ez nagy n esetén nagyságrendekkellehet kisebb n2-nél.

    Az útkereső algoritmusok gyakorlati alkalmazásai során adódó hálózatok legtöbbször ritkagráfok. Az Euler-féle poliédertétel egyszerű következménye, hogy ha egy egyszerű (irányítatlan)síkgráf minden tartománya legalább 3 csúcsú, akkor az élek száma legfeljebb 3n. Egy földitérkép úthálózata tehát tipikusan ritka gráfot határoz meg.

    A Nemes Tihamér versenyen is rendszerint éllistával történik a gráfok megadása:

    3.2. feladat (2010., 3. kat., 2. forduló, 3. feladat). Futár. Egy országban N város van. Azegyik városban futárok várakoznak. Ismerjük azt is, hogy az egyes városokból mennyi idő alattlehet elérni valamilyen járművel adott másik városokat. Készíts programot (futar.pas, . . . ),amely megadja, hogy minimum mennyi idő alatt jutnak el a futárok az összes városba!

    A futar.be szöveges állomány első sorában a városok száma (1 ≤ N ≤ 100), a járművekszáma (1 ≤M ≤ 5000) és a futárok kezdő helye (1 ≤ H ≤ N) van, egy szóközzel elválasztva.

    A következő M sorban egy-egy járművet leíró 3 szám szerepel, egy-egy szóközzel elválasztva:az indulás helye (1 ≤ Ai ≤ N), az érkezés helye (1 ≤ Bi ≤ N), valamint az út megtételéhezszükséges idő (1 ≤ Ti ≤ 1000).

    A futar.ki szöveges állományba egyetlen sort kell írni, a minimális időt, ami alatt a futárokaz összes városba elérhetnek!

    Példa:futar.be futar.ki6 12 1 351 6 20 Magyarázat:1 5 10 1→ 5: 10 időegység5 6 5 1→ 5→ 6: 15 időegység6 2 10 1→ 2: 15 időegység1 2 15 1→ 2→ 3: 25 időegység2 3 10 1→ 2→ 3→ 4: 35 időegység3 4 103 5 101 6 253 5 56 1 206 5 5

    1

    2

    3

    4

    5

    6

    15

    10

    1010 10

    5

    25

    10

    20

    20

    55

    10

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    Elképzelhető, hogy az élhosszúságokon kívül egyéb tényezőket is figyelembe kell vennünk.A következő feladat például olyan esetre mutat példát, ahol bizonyos élek igénybevétele csakakkor engedélyezett, ha elég hamar megérkezünk a kezdőpontjukba. Szerencsére ezt a nehezítéstDijkstra-algoritmus még könnyen kezelni tudja.

    3.3. feladat. Szeretnénk repülővel eljutni Budapestről Vlagyivosztokba, ez persze csak átszál-lásokkal megoldható. Holnap 8:00-kor indulunk Budapestről, a lehető legkorábban szeretnénkVlagyivosztokban leszállni. Tegyük fel, hogy rendelkezésre áll az összes számításba vehető légi-társaság menetrendje (indulási és érkezési időpontokkal). Ahhoz, hogy egy repülőjáratot hasz-nálhassunk, legalább fél órával az indulás előtt meg kell érkeznünk a megfelelő repülőtérre.Adjunk algoritmust, amely meghatározza a legkorábbi lehetséges odaérkezés időpontját.

    3.2. megjegyzés. Ha a diákok előképzettsége megengedi, érdemes egy-egy hasonló feladatot tény-legesen le is programoztatni a diákokkal.

    4. A Dijkstra-algoritmus lépésszámaLépésszámról nagyon nehéz beszélni megfelelő előképzettség nélkül. (Például: Egyáltalán mitis jelent egy lépés?) Azért a Dijkstra hatékony implementálásához kapcsolódó fő trükkök elő-hozhatók anélkül is, hogy a szokásos számításelméleti terminológiát ismernénk, használnánk.

    4.1. feladat. A megbízód ad majd egy 1000 csúcsú és 5000 élű gráfot (éllistával), ahol mindenél hossza egy-egy pozitív racionális szám. Megkapod még az s és t csúcsok sorszámait. Felada-tod, hogy megmondd a legrövidebb st-út hosszát.Van egy számolósegéded, aki a következő műveleteket tudja elvégezni: össze tud adni két ra-cionális számot, illetve két racionális számról el tudja dönteni, hogy melyik a nagyobb. Egyműveletért 1 dollárt kell fizetned a segédünknek. Összeadást és összhasonlítást magad nem vé-gezhetsz, csak a segédeddel csináltathatod. Ingyen másolhatsz át egyszer már leírt számokat.a) Elvállalnád-e a munkát, ha 2 millió dollárt ajánlanak érte? b) És 100 ezer dollárért?

    Megoldásvázlat. Az a) rész limitje alatt maradunk, ha naiv módon számoljuk össze a futás so-rán szükséges lépéseket. Minden fázis (n db) azzal kezdődik, hogy kiválasztjuk a minimumota már elért, de még nem lezárt csúcsok közül (n-nél kevesebb ilyen van). Ez eddig legfel-jebb n2 összehasonlítás. Másrészt minden él vizsgálata kapcsán végzünk egy összeadást és egyösszehasonlítást. Végeredményben tehát az dollárban mért költségünk felülről becsülhető így:

    n2 + 2m

    A b) rész limitjének teljesítéséhez ügyesebbnek kell lennünk. Az n2-en kellene spórolnunkvalamennyit. Ezt elérhetjük, ha nem végzünk minden fázis elején egy új minimumkeresést.Ehelyett, az elért csúcsokat d(v) szerint növevő sorrendben tároljuk. Ha egy új d(v) értékjelenik meg, vagy egy korábbi d(v) csökken, akkor meg tudjuk találni az a helyét a sorban log2(n)összehasonlítással (ún. bináris keresséssel: először a középsővel hasonlítjük össze stb.).

    Modellünk sajnos túlzottan is nagyvonalú. A valóságban természetesen nem lehet „ingyen”adatokat másolni, az is időt (lépésszámot vesz igénybe). Márpedig, ha az előbb vázolt módon,egyszerű növekvően rendezett listában tároljuk a csúcsainkat, akkor egy-egy új elem beszúrásaazt is maga után vonja, hogy a nála nagyobb elemeket eggyel hátrébb kell másolni a listában.

    11

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    Ez pedig már nem megy log2(n) lépésben (helyette átlagosan n/2 darab másolás kell, amivel anaiv számolással is megkapott n2-es nagyságrend fog adódni a lépésszámra).

    Szerencsére azonban ezt a problémát is meg lehet oldani, ha az adatainkat nem egyszerűrendezett listában, hanem egy trükkösebb adatstruktúrában, ún. bináris fában tároljuk.

    4.1. Bináris fák

    Vázlatosan ismertetjük a bináris fák működését. A tárgyalás során a struktúrában rejlő, mate-matikus számára is érdekes ötletre fókuszálunk; a gyakorlati megvalósítás, egyébként távolrólsem érdektelen kérdéseit meghagyjuk az informatikusoknak.

    A bináris fa csúcsaiban helyezkednek el a rendezendő elemeink. Minden csúcsnak legfeljebb2 gyereke van. Egy szülő sosem nagyobb semelyik gyermekénél. A gyökérben így mindig egyminimális elem szerepel. Végig megtartjuk a fa kiegyensúlyozott tulajdonságát is, azaz csakakkor kezdünk újabb szintet, ha az előző szint már megtelt. Így (legfeljebb) n adat esetén aszintek száma (legfeljebb) log2 n; egészen pontosan ennek egészrésze, ha a gyökeret 0. szintűnektekintjük.

    3

    4 7

    5 9 10 8

    12 6 10 13 10

    Változtassuk meg a modellünket: mostantól nemcsak az összehasonlítás és összeadás kerülpénzbe, hanem egy adat átmásolásáért is 1 dollárt kell fizetnünk (ezekre van szükségünk aDijkstra-algoritmus futtatása során). A bináris fa előnye, hogy a következő műveletek mind-egyike elvégezhető c·log2(n) dollárért (ahol c alkalmas, n-től független, előre rögzített konstans)a módosított modellben is:

    • Újabb elem beszúrása.

    • Egy elem értékének csökkentése.

    • A minimális elem törlése.

    A Dijkstra-algoritmus futtatása során éppen ezekre lesz szükségünk.Egy elem beszúrásának folyamatát ábrákkal is szemléltetjük.

    3

    4 7

    5 9 10 8

    12 6 10 13 10 6

    3

    4 7

    5 9 86

    12 6 10 13 10 10

    12

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    Az új elemet elsőre a fa legalsó szintjének első szabad helyére szúrjuk be. Összehasonlítjuka szülőjével. Ha kisebb nála, akkor kicseréljük vele. Ezután az új helyen is összehasonlítjuk aszülővel, és szükség esetén kicseréljük vele.

    3

    4 6

    5 9 7 8

    12 6 10 13 10 10

    3

    4 6

    5 9 7 8

    12 6 10 13 10 10

    6

    Mindezt addig ismételgetjük, amíg olyan helyre nem kerül, ahol már nem kisebb a szülőjénél(legkésőbb a gyökérbe érve ilyen lesz). Könnyű látni, hogy ekkor újra egy helyesen kitöltöttbináris fánk lett. Szintenként legfeljebb egyszer kellett összehasonlítanunk és két adatot ki-cserélnünk (egy csere 3 másolással könnyen megvalósítható), így a 4 log2 n korlát kényelmesentartható.

    Ha egy már a fában levő elem értéke csökken, akkor lényegében ugyanezt kell csinálnunk,csak nem kell új elemet beszúrunk.

    A minimum törlésénél egy kicsit figyelmesebbnek kell lennünk. Megtehetnénk, hogy egysze-rűen kitöröljük a gyökérből az ottani elemet, a helyére a kisebbik gyermeket írjuk, aztán annaka helyére az ő kisebbik gyermekét, stb. Így azonban a fa szépen kiegyensúlyozott struktúrájaelromolhat, az alsóbb szinteken lukak keletkeznének (és így pl. a következő elem beszúrásánálkülön kellene keresgélni, hogy hol az első szabad hely). Ezért ehelyett a következőt tesszük:a legalsó szint utolsó elemét áttesszük a gyökér helyére, és ezt lebillegtetjük : összehasonlítjuka kisebbik gyerekével, és ha nagyobb nála, kicseréljük vele; ezt addig ismételgetjük, amíg nemlesz kisebb mindegyik gyerekénél.

    4.1. megjegyzés. A Dijkstra-algoritmus gyakorlati megvalósítása esetén persze a fában valójábannem a d(v) értékeket, hanem az egyes csúcsok azonosítóját tároljuk, illetve egy ún. pointert,ami azon memóriacellákra mutat, ahol az adott csúcs d(v) értéke és egyéb adatai megtalálhatók.Ezáltal a lépésszámolás is némileg bonyolultabb a mi dollárszámításunknál, de továbbra is ac · log2 n korláton belül marad, alkalmas c konstanssal.

    4.2. Elméleti eredmények összefoglalása

    Hogy némi háttérismeretet adjunk, összefoglalunk néhány elméleti eredményt is. Ehhez beve-zetjük (felidézzük) a O(·) (ejtsd: „nagy ordó”) jelölést – pontosabban annak egy egyszerűbb,gráfalgoritmusokra használatos verzióját.

    4.2. definíció. Legyen f : N × N → N függvény. Azt mondjuk, hogy egy gráfalgoritmuslépésszáma O(f(n,m)), ha van olyan c pozitív egész szám, hogy bármilyen n csúcsú és m élűgráfra legfeljebb c · f(n) lépésben lefut az algoritmus.

    Az O(·) jelölés a lépésszám aszimptotikus viselkedésre koncentrál, biztonságos használatanémi jártasságot feltételez a határérték-számítás terén. Ezért próbáltunk eddig ennek kikerü-lésével dolgozni. Az új jelöléssel eredményeink így fogalmazhatók:

    • Naivan lépésszámolással O(n2) adódik.

    13

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    • Bináris fát használva, akkor O(n+m · log2 n) elérhető.

    A lépésszámbecslés valójában még tovább javítható. Egy bonyolultabb adatstuktúra, az ún.Fibonacci-kupac alkalmazásával O(n · log2 n +m) is elérhető. Bizonyos speciális gráfosztályokesetén, az algoritmus esetleges apró változtatásaival O(m) is elérhető.

    4.3. Néhány szó a polinomiális algoritmusokról

    Az eddigi becsléseinkben nem figyeltünk arra, hogy az egyes élekre írt számok mekkorák. Va-lójában a feladat méretét ez is befolyásolja. Nagy egyszerűsítést hajtottunk végre akkor is,amikor tetszőlegesen nagy számok másolását, összeadását és összehasonlítását engedtük egyet-len lépésben. Valószerűbb a b bites számokon végzett alapműveleteket b lépésnek tekinteni (ígypéldául az x+ y összeadás nagyjából log2 x+ log2 y lépést igényel).

    Így számolva a lépéseket, a következő általánosabb definíciót használhatjuk.

    4.3. definíció. f : N → N függvény. Azt mondjuk, hogy egy algoritmus lépésszáma O(f(n)),ha van olyan c pozitív egész szám, amelyre bármilyen n pozitív egész esetén egy n bites inputralegfeljebb c · f(n) lépésben lefut az algoritmus.

    Egy súlyozott gráf esetén az input mérete lényegében az `(e) értékek bitszámának összege(minden e élre). A Dijkstra-algoritmusra ebben az értelemben is áll az O(n2) becslés. Mivel ittf egy polinomfüggvény, a Dijkstra-algoritmus egy ún. polinomiális algoritmus. Elméleti mate-matikai szempontból a polinomiális algoritmusokra szokás hatékony algoritmusként gondolni.Egy-egy algoritmikus probléma fontos jellemzője, hogy ismert-e a megoldására polinomiálisalgoritmus. (A valóságban sajnos egy algoritmus polinomális volta nem mindig esik egybe agyakorlati felhasználhatóságával.)

    4.4. megjegyzés. Érdemes egy pillanatra visszatérni arra a korábbi algoritmus-ötletünkre, amikora súlyozott gráf minden élét `(e) hosszú úttal helyettesítettük. Ha egy `(e) értéket b bitentároltunk, akkor az e élből 2b számú új él is keletkezhet. Így az ezen alkalmazott szélességikeresés már exponenciális futásidejű lehet. Tehát valóban szükség van Dijkstra módszerére apolinomiális futásidő eléréséhez.

    5. A Dijkstra-algoritmus változatai

    5.1. Dijkstra kapacitás jellegű élsúlyokra

    Eddig az ` : E → R+ élsúlyokra mindig úgy tekintettünk, mint valamiféle költség (úthossz,idő, pénz) jellegű mennyiségre: minél kisebb, annál jobb. Egy élsúlyozás azonban kifejezhetkapacitás jellegű feltételt is. Ilyenkor persze tipikusan nem az a feladat, hogy egy úton az ilyenkapacitásokat összeadjuk, hanem hogy a legszűkebb útszakaszt is minél szélesebbre vegyük.

    5.1. feladat. Adott egy úthálózat térképe (egyszerű gráffal modellezve). Mindegyik útszakaszról(élről) tudjuk, hogy legfeljebb milyen széles teherautók közlekedhetnek rajta. Adjunk algoritmust,amely meghatározza, hogy legfeljebb milyen széles teherautóval lehet eljutni A-ból B-be.

    Bizonyítás. Megoldásvázlat Jelölje G = (V,E) a gráfot és w : E → R+ az egyes útszakaszokszélességét. Egy út szélessége jelentse a legkeskenyebb élének szélességét, keressük a legszélesebbst utat. Futassuk a Dijskstra algoritmust a következő módosításokkal:

    14

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    • d(v) jelentse az (eddig megtalált) legszélesebb sv út szélességét.

    • A d(v) értékek update-elésére a korábbi

    d(u) + `(u, v) < d(v) esetén d(u) + `(u, v)→ d(v)

    szabály lépés helyett ezt vezetjük be:

    min{d(u), w(u, v)} > d(v) esetén min{d(u), w(u, v)} → d(v)

    • Az átvizsgálásra kerülő csúcs mindig a legnagyobb d(v) értékű, nem lezárt csúcs.

    Az eredetihez hasonló módon belátható a módosított algoritmus helyessége is.

    Erre az észrevételre is épült már informatikai versenyfeladat:

    5.2. feladat (2011., 3. kat., 3. forduló 1. feladat). Egy ország N városa között különbözőteherbírású utak vannak. Két város között árut szeretnénk szállítani a lehető legnagyobb kapa-citású teherautóval olyan útvonalon, ahol az autó tehersúlya nem nagyobb, mint az egyes utakteherbírása.

    Készíts programot (szallitas.pas, szallitas.c, . . . ), amely adott A és B városra megadja, hogymaximum mekkora tehersúlyú teherautó közlekedhet közöttük és merre kell menni!

    A szallitas.be állomány első sorában a városok száma (1 ≤ N ≤ 100), a köztük levő utakszáma (1 ≤ M ≤ 10000), a kezdő és a cél város sorszáma (1 ≤ A 6= B ≤ N) van, egy-egy szóközzel elválasztva. A következő M sor mindegyikében egy-egy út leírása található: azonkét város sorszáma (1 ≤ sorszám ≤ N), amelyek között a kétirányú út vezet, valamint az útteherbírása (1 ≤ tehebírás ≤ 1000).

    Az szallitas.ki szöveges állományba 2 sort kell írni. Az elsőbe a maximális tehersúly kerüljön,a másodikba pedig az oda vezető úton levő városok sorszáma, egy-egy szóközzel elválasztva, azútvonal sorrendjében (azaz az első sorszám biztosan A, az utolsó sorszám biztosan B legyen)!Több megoldás esetén bármelyik megadható.

    Példa:

    szallitas.be szallitas.ki5 6 3 4 3002 1 100 3 5 41 4 1003 1 2003 5 3002 3 9004 5 400

    1 2

    34

    5

    100

    200100 900

    300400

    5.2. Ha több legrövidebb út van

    Korábban láttunk módot egy legrövidebb út kiolvasására. Nem biztos azonban, hogy csakegyetlen legrövidebb út van.

    5.3. feladat. Mi a helyzet, ha minden útszakasznak van hossza és útdíja is? Minimális útdíj-költséggel, ezen belül pedig a lehető legrövidebb úton szeretnénk eljutni S-ből T -be. Hogyan lehetmegtalálni az optimális utat?

    15

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    Kétféle megoldás is van, külön-külön mindegyik igen tanulságos.

    I. megoldás. Jelölje `(e) az e él hosszát, míg c(e) az útdíj-költséget. Minden e élhez rendeljükhozzá az (c(e), `(e)) számpárt. Két ilyen számpárt össze tudunk adni: (c1, `1) + (c1, `2)) =(c1 + c2, `1 + `2). Össze is tudjuk hasonlítani ezeket: (c1, `1) < (c2, `2)), ha c1 < c2 vagy c1 = c2és `1 < `2. Tegyük az élsúlyok helyébe ezeket a számpárokat. Összeadni és összehasonlítanitudjuk őket, tehát a Dijkstra algoritmust is tudjuk futtatni. Ennek eredményeképp egy olyanutat kapunk, amelyen a (c, `) számpárösszeg minimális, azaz a c-összeg optimális, ezek közöttaz `-összeg is minimális.

    5.1. megjegyzés. A f(v) = (c(e), `(e)) számpárok aritmetikájára úgy is gondolhatunk, mint hac(e) ·M + ` számokkal dolgoznánk, ahol M egy rögzített, nagyon nagy szám.

    A II. megoldás a pontos élek fogalmára épít. Ezt a következő feladat kapcsán tudjuk meg-ismerni.

    5.4. feladat. Súlyozatlan gráfok esetében ismert, hogy egy st út pontosan akkor legrövidebb azst-utak között, ha minden éle 1-et lép lefele a szélességi fában.Tudsz-e hasonló jellemzést adni súlyozott élek esetén?

    A megoldás a következő definíció.

    5.2. definíció. Legyen G = (V,E, `) egy irányított gráf nemnegatív élhosszfüggvényekkel el-látva (az irányítatlan eset tekinthető oda-vissza irányított gráfnak). Legyen s ∈ V rögzített ésjelölje d(v) az s-ből v-be menő legrövidebb út hosszát (minden v ∈ V csúcsra). Ekkor egy uwél pontos, ha d(w)− d(u) = `(uw).

    Nem nehéz belátni a következő állítást:

    5.3. állítás. Egy st út pontosan akkor minimális összhosszúságú, ha minden éle pontos.

    II. megoldás a 5.3 feldatra. Futtassuk le a Dijkstra-algoritmust c útdíjak szerint. Ezután fut-tassuk ` szerint a Dijkstra-algoritmust, de ne az egész gráfon, hanem csak a c költség szerintpontos élek halmazán.

    A 5.1 és 5.3 feladatok kombinációja a következő feladat:

    5.5. feladat. Egy úthálózat minden szakaszának tudjuk a hosszát és az adott szakaszon meg-engedett maximális tömeget is. A lehető legrövidebb útón, ezen belül a lehető legnehezebb szál-lítmányt szeretnénk eljuttatni s-ből t-be. Hogyan lehet megtalálni az optimális utat?

    5.3. Leghosszabb utak

    Természetes módon merülhet fel egy diákban, hogy ha a legrövidebb utakat ilyen hatékonyanmeg tudjuk keresni egy s és t pont között, akkor mi a helyzet a leghosszabb/legdrágább utakkal.Ismert-e erre is hatékony (polinomiális) algoritmus?

    Erre negatív válasz adható, már a súlyozatlan gráfok esetén is. Ha ugyanis lenne hatékonyalgoritmus erre, akkor lenne hatékony algoritmus az algoritmuselmélet egyik leghíresebb megol-datlan problémájára, a Hamilton-kör létezésének eldöntésére. Feladatat formájában is érdemesfeladni a következőt:

    16

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    5.6. feladat. Tegyük fel, hogy a LongRoad2015 nevű algoritmus tetszőleges gráfban tetsző-leges s, t csúcspárra megmondja, hogy hány élből áll a leghosszabb út s és t között. Csináljunkolyan algoritmust, ami egy m élű gráfra el tudja dönteni, hogy van-e benne Hamilton-kör, aLongRoad2015 legfeljebb m-szeri meghívásával.

    Bizonyítás. Legyen uv az n csúcsú és m élű G gráfunk egy tetszőleges éle. Hagyjuk ki ideig-lenesen az uv élt a gráfból és alkalmazzuk a LongRoad algoritmust u, v csúcspárra a maradékgráfban. Pontosan akkor talál n− 1 élű utat az algoritmus, ha G-ben van olyan Hamilton-kör,ami uv élt tartalmazza (egyébként csak rövidebbet).

    Ezt G összes élére megismételve kiderül, hogy van-e Hamilton-kör a gráfban.

    5.4. megjegyzés. Számítástudományi nyelven éppen azt jelenti feladatunk állítása, hogy a leg-hosszabb út megkeresése NP-nehéz probléma. Azaz, ha lenne polinomiális algoritmus erre afeladatra, akkor egy rakat mindmáig megoldatlan (és sokak által megoldhatatlannak is tartott)algoritmuselméleti problémára lenne polinomiális algoritmusunk.Az NP-nehéz problémákról részletesebben pl. [2]-ben lehet olvasni.

    6. Negatív költségű élek6.1. feladat. Mutassunk példát arra, hogy ha negatív költségű éleket is megengedünk, akkor aDijkstra algoritmus nem ad feltétlenül minimális összköltségű utat.

    6.2. feladat. Adott egy irányított gráf, és élein egy c : A → R költségfüggvény, mely negatívértékeket is felvehet. Egy megfelelő konstanssal minden élen megnöveljük c-t úgy, hogy a kapottc′ nemnegatív legyen. Igaz-e, hogy ekkor c′-re alkalmazva a Dijkstra-algoritmust az eredeti cköltségfüggvény szerint is legrövidebb utat kapunk?(A költségfüggvény milyen módosítása nem változtat a legrövidebb utak halmazán?)

    Válasz. Könnyű ellenpéldát adni.

    A 5.6 feladathoz hasonlóan oldható meg a következő feladat:

    6.3. feladat. Tegyük fel, hogy a NegativeRoad2015 nevű algoritmus tetszőleges gráfban, tet-szőleges c : E → R költsdégfüggvényre és s, t csúcspárra megmondja, hogy a minimális st útösszköltségét. Csináljunk olyan algoritmust, ami egy m élű gráfra el tudja dönteni, hogy van-ebenne Hamilton-kör, a NegativeRoad2015 legfeljebb m-szeri meghívásával.

    A feladat azt mondja nekünk, a negatív költségfüggvényes változat általánosan NP-nehéz,mivel lehetne vele Hamilton-kört keresni.

    Ismert azonban egy viszonylag természetes megkötés, ami mellett már megoldható a negatívélköltségeket is megengedő eset (igaz, nem a Dijkstra-algoritmussal, hanem az ún. Bellman–Fordalgoritmussal):

    6.1. definíció (Konzervatív súlyozás). Legyen G = (V,E) egy irányított gráf. Egy c : E → Rköltségfüggvényt konzervatívnak nevezünk, ha nincsen olyan egyirányba irányított kör, amelyen

    6.2. megjegyzés. Természetes példa lehet konzervatív súlyozásra egy energiát visszatáplálni ké-pes villamoshálózat.

    17

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    A konzervatív élsúlyozásokkal kapcsolatos tételekről, fogalmakról és algoritmusokról (Gallaitétele, tenziók, Bellman–Ford algoritmus, Floyd–Warshall algoritmus) [1]-ban részletesen lehetolvasni. A konzervatív súlyozások vizsgálata során felmerülő kérdések közül egyet jól mutat bea következő feladat:

    6.4. feladat. Egy svájci vasúttársaság módosítja a jegyárait. Magassági pótlékot ill. kedvez-ményt vezetnek be, tekintettel arra, hogy hegyre fel a villanyvonatoknak többletenergiára vanszüksége, ugyanakkor lejtmenetben a modern villanyvonatok akár energiát visszatáplálni is ké-pesek a rendszerbe. Ennek rendje a következő: ha a járat kiinduló városa h1 méter tengerszintfeletti magasságban van, míg a célállomás h2 méter magasságban, akkor a jegy árát h2 − h1rappennel 2 emelik ill. csökkentik, a különbség előjelének megfelelően (minden jegyár pozitívmarad).Lehetséges-e, hogy a módosítás hatására A-ból B-be egy másik útvonalon lesz a legolcsóbb eljutni,mint korábban? Lehetséges-e, hogy a Dijkstra-algoritmus másik utat talál meg legrövidebbként?

    Megoldás. Minden st út összhossza ugyanannyival változik: h(t)− h(s)-sel növekszik ill. csök-ken a különbség előjelétől függően. Így változatlan a legolcsóbb utak halmaza.

    A Dijkstra-algoritmus átvizsgálási sorrendje azonban megváltozhat. Így, ha többféle legrö-videbb út is van, lehetséges, hogy másikat talál meg ezek közül. Egy példát ad erre a következőgráf:

    s (0 m)

    w (1000 m)

    v (3000 m)

    t (0 m)

    2

    1

    3

    4

    Az eredei gráfon a Dijkstra az svt utat választaná, de a magasságpótlék bevezetése után máraz swt kerül kiválasztásra.

    7. Gyakorlati alkalmazások – az A*-algoritmusA legrövidebb utak megkeresése egy igazán gyakorlati probléma, gondolhatunk például a na-vigációs rendszerek útvonaltervezőire. Ezekben az alkalmazásokban tipikusan nem az általunkmegismert Dijkstra-algoritmust, hanem annak valamilyen módosított változatát használják. Amódosítások alapja általában a vizsgált hálózat sajátosságainak ügyes kihasználása. Nem ja-vítják meg Dijkstra módszerét általánosan (nem is ismert olyan módszer, ami minden súlyozottgráfra hatékonyabban működne, mint a Dijkstra-algoritmus); de a konkrét térkép esetébenmégis jobban működnek.

    Egy tipikus ötletek közül az egyik jól bemutatható az alábbi feladattal. A válasz még némimatematikai érdekességet is rejt magában.

    2100 rappen = 1 svájci frank

    18

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    7.1. feladat. Az alábbi térkép Franciország nagyvárosai közötti közúti összeköttetéseket mutat-ja, az egyes összeköttetések mellé írták az adott útszakasz hosszát, kilométerben.Tegyük fel, hogy Párizsból Marseille-be szeretnénk eljutni a legrövidebb úton. Hogyan futna ezena feladaton a Dijkstra-algoritmus? Mennyiben más ez, mint ha józan ésszel, a térképet követvepróbálnánk legrövidebb utat találni?

    A kép forrása: http: // www. bonjourlafrance. com/ france-map/ images/ france-driving-distances. jpg

    A Dijkstra-algoritmus a Párizsból kiinduló éleket minden irányban megvizsgálná. Így pél-dául a keresés során eljutna az északi Lille-be, vagy a keleti Strasbourgba is, pedig a térképrerátekintve látszik, hogy ezeket értelmetlen útba ejteni. Hogyan lehetne az algoritmusunkat ettőla felesleges munkától megkímélni? Erre kínál egy lehetőséget az A*-algoritmus.

    19

    http://www.bonjourlafrance.com/france-map/images/france-driving-distances.jpg

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    7.1. Az A*-algoritmus

    Tegyük fel, hogy van valamilyen előre ismert becslésünk minden v csúcs esetén a legrövidebbvt út összhosszára. Jelölje h : V → R+ azt a heurisztikus távolságfüggvényt, amelyre h(v)a (v, t) párra adott becslés értéke. Például h(v) lehet a v és t csúcsoknak megfelelő városoklégvonalbeli távolsága.

    A szokásos módon, egy már elért csúcsra jelölje d(v) az eddig megtalált legrövidebb sv úthosszát. Tekintsük a következő összegeket minden csúcsra:

    f(v) = d(v) + h(v).

    Az A*-algoritmusban a Dijkstra-algoritmust módosítjuk a következőképpen: a soron követ-kező csúcsot nem a d(v) hanem az f(v) értékek alapján határozzuk meg: a következő átvizs-gálandó mindig egy minimális f(v) értékű (nem lezárt) csúcs. Leállíthatjuk az algoritmust,ha már minden olyan csúcs le van zárva, aminek aktuális f(v) értéke kisebb az aktuális d(t)értéknél; azokat a csúcsokat, amelyeket eddig nem zártunk le, később sem fogjuk átvizsgálni.

    Könnyű példát adni olyan gráfra és h függvényre, amikor ez a módosítás elrontja a Dijkstra-algoritmust, az új változat nem találja meg a legrövidebb sv utakat. A hiba egyik oka az, hogyegy v csúcs lezárásakor még nem biztos, hogy a legrövidebb sv utat ismerjük. A módosítottátvizsgálási sorrend miatt elképzelhető, hogy egy későbbi u csúcsból találunk egy olyan uv élt,amelyre d(u)+ `(u, v) < d(v) teljesül. Ilyenkor v csúcs d(v) értékét javítsuk ki, és tegyük visszaN állapotba!

    Sajnos még mindig nem garantálható, hogy az optimális sv utat fogjuk megtalálni. Azon-ban, ha h teljesít egy viszonylag természetes elvárást, akkor az A* biztosan a legjobb st utatfogja megtalálni.

    7.2. feladat. Bizonyítsd be, hogy ha a h : V → R+ optimista, azaz h(v) alulról becsüli alegrövidebb vt út hosszát minden v ∈ V esetén, akkor az A*-algoritmus egy optimális utat találmeg.

    Megoldás. Jelölje minden v csúcsra d∗(v) a legrövidebb (minimális `-összegű) sv út hosszát.Legyen sv1v2 . . . vkt egy legrövidebb st-út. A 2.3 feladat alapján ez minden vi-be is egy legrö-videbb utat határoz meg. Azt állítjuk, hogy az út minden csúcsa lezárásra kerül, méghozzá azoptimális d∗(vi) értékkel. (Innen egyből következik a feladat állítása.)

    i szerinti indukcióval bizonyítunk. i = 0 (v0 = s) eset triviáis. Tegyük fel, hogy vi−1-remár beláttuk, következik vi. Tekintsük az algoritmus leállásának pillanatát (tehát amikor tcsúcsot lezártuk). A feltevésünk szerint vi−1 lezárásra került d∗(vi−1) értékkel. vi−1 utolsóátvizsgálásakor a vi−1vi élt is néztük, tehát vi-t is el kellett érjük d∗(vi) hosszúságú (azazoptimális) úton. Ez azt is jelenti, hogy az algoritmus leállásának pillanatában teljesül:

    f(vi) = d∗(vi) + h(vi) ≤ d∗(t).

    Itt az utolsó≤ azért igaz, mert h(vi) az optimista tulajdonság miatt alulról becsüli a vivi+1 . . . vktút hosszát, ami éppen d∗(t) − d∗(vi). A kapott f(vi) < d∗(t) azt jelenti, hogy az algoritmusleállásakor vi-nek is lezárva kell lennie a d∗(vi) értékkel.

    Az esetleges visszanyitások miatt egy csúcs többször is átvizsgálásra kerülhet, így az A*akár lassabb is lehet, mint a jó öreg Dijkstra-algoritmus. Szerencsére egy másik h-ra vonatkozóelvárás ezt az eshetőséget is kizárja.

    20

  • Hujter Bálint: Dijkstra algoritmusa SpecMat továbbképzés, 2015. július 1.

    7.3. feladat. Bizonyítsd be, hogy ha a h : V → R+ monoton, azaz minden uv élre:

    h(u) ≤ `(u, v) + h(v),

    akkor az A*-algoritmus minden csúcsot legfeljebb egyszer vizsgál át.

    Megoldás. Azt kell meggondolni, hogy sosem kerül sor egy már lezárt csúcs visszanyitására.Indirekt tegyük fel, hogy v csúcsot vissza kell nyitnunk, méghozza egy u szomszédjának át-vizsgálásakor. Erre azért kerülhet sor, mert az aktuális d értékekkel d(u) + `(u, v) < d(v). Amonotonitás miatt h(u)− `(u, v) ≤ h(v). Összeadva a két egyenlőtlenséget:

    f(u) = d(u) + `(u, v) + h(u)− `(u, v) < d(v) + h(v) = f(v).

    Ez ellentmond annak, hogy v-t már az u mostani vizsgálata előtt átvizsgáltuk egyszer.

    7.1. megjegyzés. Amennyiben a gráf csúcsai városok, `(u, v) a közúti távolság és h(v) a légvo-nalbeli vt távolság, akkor h optimista és monoton is.

    7.2. megjegyzés. Valójában az A*-algoritmus név egyszerre több, csak apróságokban különbözőalgoritmust takar, mi ezek közül választottunk egyet. További rokonai a B* és D* keresésialgoritmusok.

    Hivatkozások[1] Frank András, Király Tamás: Operációkutatás, Egyetemi jegyzet (2013), letölthető:

    http://etananyag.ttk.elte.hu/FiLeS/downloads/_Frank_Kiraly_Operaciokut.pdf

    [2] Lovász László: Algoritmusok bonyolultsága, Egyetemi jegyzet (2014), letölthető:http://etananyag.ttk.elte.hu/FiLeS/downloads/16_LOVASZ_Algor_bonyol.pdf

    [3] ELTE Egerváry Jenő Kutatócsoport: Operációkutatás példatár (2013), letölthető:http://etananyag.ttk.elte.hu/FiLeS/downloads/_Opkut_peldatar.pdf

    [4] https://en.wikipedia.org/?title=Dijkstra%27s_algorithm

    [5] https://en.wikipedia.org/wiki/A*_search_algorithm

    [6] Nemes Tihamér Országos Informatikai Tanulmányi Verseny archívuma(Programozás kategória) http://nemes.inf.elte.hu/nemes_archivum.html

    21

    http://etananyag.ttk.elte.hu/FiLeS/downloads/_Frank_Kiraly_Operaciokut.pdfhttp://etananyag.ttk.elte.hu/FiLeS/downloads/16_LOVASZ_Algor_bonyol.pdfhttp://etananyag.ttk.elte.hu/FiLeS/downloads/_Opkut_peldatar.pdfhttps://en.wikipedia.org/?title=Dijkstra%27s_algorithmhttps://en.wikipedia.org/wiki/A*_search_algorithmhttp://nemes.inf.elte.hu/nemes_archivum.html

    Legrövidebb utakDijkstra algoritmusaA Dijkstra-algoritmus részletes ismertetéseAz algoritmus futása egy konkrét gráfonAz algoritmus helyességének igazolásaA legrövidebb utak kiolvasásaA Dijkstra-algoritmus fizikai modellje

    Irányított gráfok. Gráfok és feladatok megadási módjaiA Dijkstra-algoritmus lépésszámaBináris fákElméleti eredmények összefoglalásaNéhány szó a polinomiális algoritmusokról

    A Dijkstra-algoritmus változataiDijkstra kapacitás jellegu élsúlyokraHa több legrövidebb út vanLeghosszabb utak

    Negatív költségu élekGyakorlati alkalmazások – az A*-algoritmusAz A*-algoritmus

    Hivatkozások