Tietorakenteet, esimerkkivastauksia viikon laskareiin (a) Oletetaan seuraavan kuvan mukainen verkko ja etsitään lyyimpiä polkuja solmusta Ensimmäiseksi käsitellään solmu B, jonka etäisyys on kolme Seuraavaksi solmu, jonka on etäisyyeksi tulee B:n kautta Viimiseksi käsiteltävä solmu on, joka saa etäisyyekseen 00 :n käsittelyn yteyessä muutetaan etäisyyttä solmuun, jonka etäisyyeksi saaaan neatiivisen kaaren ansiosta loritmin suoritus on päättynyt, mutta solmuun B jotaisikin :n ja :n kautta polku, jonka kustannukseksi tulee 00 99 + = 0 00 00 B B 0 0 00 00 B B 00 () Jos kaikkien kaarien painoa lisätään saalla, ei neatiivisa kaari enää ole Nyt kuitenkin lyin polku solmusta solmuun B ei kulje enää alkuperäisen verkon tapaan solmujen ja kautta, sillä polun pituueksi tulee 00++0 = 0 kun suran kaaren a paino on vain 0 Floy-Warsall-aloritmi laskee jokaiselle verkon solmulle i ja j, kuinka pitkä on lyin polku, joka alkaa i:stä ja päättyy j:in loritmin toimintaa eivät äiritse maolliset verkossa olevat neatiiviset polut Kuitenkaan verkossa ei saa olla neatiivisia syklejä: silloin syklin sisältävää polkua voisi lyentää loputtomasti kulkemalla sykliä uuestaan ja uuestaan Floy-Warsall-aloritmi pitää kirjaa lyimmistä poluista matriiseissa k Oletetaan seuraavaksi, että verkossa on n solmua, jotka on numeroitu,, n Nyt kussakin matriisissa koassa k [i,j], eli rivillä i sarakkeessa j, lukee, kuinka pitkä on lyin verkossa oleva polku, joka alkaa solmusta i, päättyy solmuun j ja joka voi kulkea solmujen,,, k kautta käyttäen niitä välisolmuina Tutkitaan seuraavaksi Floy-Warsall-aloritmin toimintaa tetävässä annetulla verkolla Verkossa solmujen tunnukset ovat a,, ja korvataan ne nyt vastaavasti numeroilla,, ja
9 Matriisiin 0 merkitään lyimmät polut, joissa ei ole välisolmuja Jos alkusolmu ja loppusolmu ovat samat, polun pituueksi merkitään 0, koska solmujen välillä on tyjä polku Jos alkusolmusta on kaari loppusolmuun, polun pituueksi merkitään tämän kaaren pituus Muuten alkusolmusta ei pääse loppusolmuun kulkematta välisolmujen kautta, joten polun pituueksi merkitään ääretön (ei polkua) 0 = 0 0 0 9 0 Matriisiin merkitään lyimmät polut, jotka saavat kulkea solmun kautta Tässä verkossa kuitenkaan solmu ei ole yöyllinen välisolmu, koska mistään solmusta ei pääse solmuun eikä se voi lyentää mitään polkua Tämän vuoksi matriisi vastaa matriisia 0 = 0 0 0 9 0 Matriisiin merkitään lyimmät polut, jotka saavat kulkea solmujen ja kautta Kun solmun sallitaan olevan välisolmuna, verkkoon ilmestyy yksi uusi polku: solmusta pääsee solmuun kulkemalla ensin solmusta solmuun ja sitten solmusta solmuun = 0 0 0 9 0
Matriisiin merkitään lyimmät polut, jotka saavat kulkea solmujen, ja kautta Uusi välisolmu tuo verkkoon kaksi uutta polkua: solmuista ja pääsee solmuun kulkemalla solmun kautta = 0 0 0 0 9 0 Matriisiin merkitään lyimmät polut, jotka saavat kulkea solmujen,, ja kautta eli kaikkien verkon solmujen kautta Ensinnäkin polku solmusta solmuun lyentyy kulkemalla suoran kaaren sijasta solmujen ja kautta Lisäksi solmusta pääsee nyt solmuun solmun kautta = 0 0 0 0 9 0 Nyt aloritmin suoritus on valmis ja matriisi sisältää lyimmän polun pituuen mistä taansa verkon solmusta miin taansa verkon solmuun Solmuun ei pääse mistään verkon solmusta, kun taas solmuiin, ja pääsee kaikista verkon solmuista Vastaavasti solmuun ei tule kaaria ja solmut, ja muoostavat syklin Lisäaaste: Otetaan käyttöön kaksiulotteinen taulukko polku Taulukon alkio polku[i, j] kertoo jonkin solmun, jonka kautta toistaiseksi tunnettu lyin i:n ja j:n välinen polku kulkee tai jos lyin tunnettu etäisyys solmujen välillä on niien välinen suora kaari (niinkuin tilanne on alussa), on polku[i, j] = j loritmin laskennan aikana polku[i, j] päivitetään arvoon k jos solmun k kautta kulkeminen aieuttaa [i,j]:n päivityksen: Floy-Warsall-v() for i = to n for j = to n if i == j [i,j] = 0 else [i,j] = [i,j] if [i,j] = 7 polku[i,j] = 8 else polku[i, j] = j 9 for k = to n 0 for i = to n for j = to n if [i,k] + [k,j] < [i,j] [i,j] = [i,k] + [k,j] polku[i,j] = k Kun alutaan eneroia lyin polku solmusta i solmuun j, kertoo polku[i, j] siis jonkin solmun jonka kautta lyin polku kulkee Jos polku[i,j] =, ei solmusta i ole polkua solmuun j Jos
polku[i,j] = j, on solmujen välinen lyin polku niien välinen suora kaari ja lyintä polkua ei tarvitse sen kummemmin selvittää Jos polku[i,j] = k, missä k j, on lyin polku siis i k j Väleillä i k ja k j voi olla useita solmuja polku[i,k] kertoo taas jonkun solmun joka on lyimmällä polulla i k Näin löytyy jälleen yksi solmu joka on lyimmän polun i j varrella Vastaavasti polku[k,i] kertoo jonkun solmun joka on lyimmällä polulla k i Lyin polku solmujen alku ja loppu välillä voiaan tulostaa alla olevan rekursiivisesti toimivan metoin avulla kutsumalla sitä lyinpolku(alku,loppu): lyinpolku(i,j) if polku[i,j] = j // i:n ja j:n lyin polku on suora kaari print(j) else k = polku[i,j] lyinpolku(i,k) lyinpolku(k,j) Kruskalin aloritmin ensimmäisessä vaieessa järjestetään kaaret painon mukaan kasvavasti (ja tetävän oletuksen mukaisesti saman painoiset aakkosjärjestyksessä): (a,), (,), (,f), (f,), (,e), (,), (,), (,), (,), (e,f), (a,e), (,f), (,) Sitten käyään läpi kaaret eellä saaussa järjestyksessä ja otetaan kaari mukaan, jos se yistää kaksi erillistä virittävän metsän komponenttia Lopputuloksena saaaan seuraava pienin virittävä puu: a e f Jos samanpainoisia kaaria ei käyäkään läpi aakkosjärjestyksessä, saatetaan päätyä myös toisenlaiseen pienimpään virittävään puuun: Jos kaari (f,) käsitellään ennen kaarta (,f) ja muuten kuten eellä, niin saaaan puu a e f Jos taas kaari (e, f) käsitellään ennen kaarta (, ) ja muuten kuten ensimmäisellä kerralla, saaaan puu
a e f Jos kaari (f,) käsitellään ennen kaarta (,f) ja kaari (e,f) ennen kaarta (,), saaaan puu a e f Kaarten (,e) ja (,) käsittelyjärjestys ei vaikuta pienimmän virittävän puun rakenteeseen, koska molemmat kaaret tulevat mukaan joka tapauksessa Tarkastellaan verkkoa, jonka solmuina on lentokenttiä ja kaarina suorat lennot kultakin lentokentältä jollekin toiselle lentokentälle Kunkin kaaren painona on toennäköisyys sille, että matkatavarat katoavat tällä lennolla Merkataan P(x,x,,x n ):llä toennäköisyyttä sille, että matkatavarat katoavat jollakin lennolla (x i,x i+ ) kun lennetään lentoasemalta x lentoasemalle x n lentoasemien x,,x n kautta Toennäköisyyet P(x i,x j ), joissa on vain kaksi lentoasemaa i ja j, ovat siis annetut verkon kaarien painot Se, että matkatavarat katoavat jollain lennolla on vastatapatuma sille, että matkatavarat eivät katoa millään lennolla, eli P(x,x,,x n ) = ( P(x,x )) ( P(x,x )) ( P(x n,x n )) Tämä saa pienimmän arvonsa kun tulo ( P(x,x )) ( P(x n,x n )) saa suurimman arvonsa Loaritmin avulla tämä tulo saaaan muunnettua summaksi Loaritmin kantaluku a voiaan valita vapaasti Koska loaritmi on aiosti kasvava funktio, tämä tulo saa suurimman arvonsa kun lo a (( P(x,x )) ( P(x,x )) ( P(x n,x n ))) = lo a ( P(x,x )) + lo a ( P(x,x )) + + lo a ( P(x n,x n )) saa suurimman arvonsa, joka eellyttää eelleen sitä, että lo a ( P(x,x )) lo a ( P(x,x )) lo a ( P(x n,x n )) saa pienimmän arvonsa Siis korvaamalla verkon kunkin kaaren (i, j) painon painolla lo( P(x i,x j )) (joka on aina positiivinen luku, koska P(x i,x j ) on toennäköisyytenä aina korkeintaan ) voiaan etsiä ne lentoreitit, joilla matkatavaroien katoamisen toennäköisyys on pienin maollinen käyttämällä suoraan tavallista ijkstran aloritmia Rautatieverkosto on esitetty verkkona G = (V, E), jonka solmuina on kaikki rautatieliikennepaikat ja kaarina niien väliset ratayteyet Kutakin ratayteyttä (u,v) meneville kuljetuksille on asetettu maksimipaino w(u, v) Tetävänä on määrittää suurin paino, jolle voiaantaata rautatiekuljetus minkä taansa kaen liikennepaikan välillä
Ratkaisu Jos junan paino p tieetään, on elppoa tarkastaa, voiko junalla ajaa miltä taansa asemalta toiselle Tämä tapatuu valitsemalla jokin verkon solmu ja aloittamalla siitä verkon syvyyssuuntainen läpikäynti niin, että vain kaaret, joien paino on ainakin p, otetaan mukaan Jos lopuksi kaikissa verkon solmuissa on vierailtu, juna pystyy siirtymään kaikkien asemien välillä eikä paino p ei ole liian suuri Eellisen perusteella onelman voi ratkaista käymällä kaikki junan maolliset painot läpi ja valitsemalla niistä suurin kelvollinen Junan suurin sallittu paino on varmasti jokin liikennepaikkojen välisistä painoista, koska muuten junan painoa voisi vielä nostaa pilaamatta ytään reittiä Junan maollisia painoja on E ja yksi verkon läpikäynti vie aikaa O( E ), joten kokonaisaikavaativuus on O( E ) Ratkaisua voi vielä teostaa järjestämällä ensin junan maolliset painot ja etsimällä niistä suurin kelvollinen inääriaulla Nyt järjestämiseen kuluu aikaa O(lo( E ) E ) ja oikean painon löytämiseen kuluu aikaa O(lo( E ) E ), joten kokonaisaikavaativuus on O(lo( E ) E ) Ratkaisu Toinen tapa ratkaista onelma on muoostaa verkon suurin virittävä puu ja ilmoittaa junan painoksi puun keveimmän kaaren paino Verkon suurin virittävä puu on verkon virittävä puu, jonka kaarten yteispaino on maollisimman suuri Verkon suurimman virittävän puun voi löytää muuttamalla verkon kaikkien kaarten painot neatiivisiksi ja etsimällä näin saaun verkon pienin virittävä puu Tetävän Kruskalin ja Primin aloritmit toimivat myös silloin, kun verkossa on neatiivisia kaaria Verkon suurin virittävä puu, kuten jokainen muukin virittävä puu, kytkee varmasti kaikki verkon solmut toisiinsa Puun kaarten painojen summa on suurin maollinen, mutta tämä ei vielä takaa, että myös keveimmän kaaren paino on suurin maollinen Seuraava tarkastelu osoittaa kuitenkin, että suurin virittävä puu ei voi sisältää kaarta, jota raskaampia kaikki jonkin toisen virittävän puun kaaret olisivat Oletetaan, että verkon suurimman virittävän puun kevein kaari k on solmujen a ja välillä Jos tämä kaari poistetaan, verkko jakaantuu kateen erilliseen osaan ja B Missä taansa virittävässä puussa täytyy olla jokin polku a:sta :en, jonka täytyy jossain vaieessa siirtyä :sta B:en Jos olisi saatavilla kaari k, joka siirtyy :sta B:en ja on raskaampi kuin kaari k, virittävän puun voisi kenties muoostaa niin, että sen kevein kaari on raskaampi kuin k Mutta myös alkuperäisessä puussa :n ja B:n välille voisi valita kaaren k, jolloin kaarten yteispaino kasvaisi eikä alkuperäinen puu olisikaan suurin virittävä puu Tässä ratkaisussa pääosan ajasta vie suurimman virittävän puun muoostus Kruskalin ja Primin aloritmien perustoteutusten aikavaativuuet ovat luokkaa O(lo( E ) E ), joten ratkaisun ja ratkaisun teokkuusero ei vaikuta suurelta