Helsingin yliopisto, University of Helsinki
MOOC.FI

Viikko 12

Viikon aiheena on pienimmät virittävät puut ja union find. Pienimmän virittävän puun löydät esimerkiksi Kruskalin algoritmilla.

Tehtävä 1

Tehtäväsi on pitää kirjaa ystäväverkostosta, johon ilmestyy uusia suhteita.

Toteutus

Toteuta luokka Ystavat, joka tarjoaa seuraavat metodit:

  • Ystavat(int n): konstruktorille annetaan henkilöiden määrä (kokonaisluku välillä 1..105)
  • void lisaaYstavyys(int a, int b): henkilöt a ja b ystävystyvät
  • int suurinRyhma(): metodin tulee palauttaa, kuinka suuri on sillä hetkellä suurin ryhmä henkilöitä, jotka kytkeytyvät toisiinsa ystävyyssuhteiden välityksellä

Aluksi kukaan ei ole ystävä kenenkään kanssa. Testauksessa metodeita kutsutaan enintään 105 kertaa.

Esimerkit

Seuraava koodi testaa luokkaa:

Ystavat y = new Ystavat(4);
System.out.println(y.suurinRyhma());
y.lisaaYstavyys(1, 2);
System.out.println(y.suurinRyhma());
y.lisaaYstavyys(3, 4);
System.out.println(y.suurinRyhma());
y.lisaaYstavyys(1, 4);
System.out.println(y.suurinRyhma());

Koodin tulostuksen tulisi olla seuraava:

1
2
2
4

Tehtävä 2

Tieverkosto on päässyt huonoon kuntoon, ja se tulisi kunnostaa. Rahaa on kuitenkin vähän, eikä kaikkia teitä voi korjata. Tehtäväsi on etsiä sellainen joukko teitä, että minkä tahansa kahden kaupungin välillä pystyy kulkemaan vain korjattuja teitä ja kokonaiskustannus on mahdollisimman alhainen.

Toteutus

Toteuta metodi: long kunnostus(int n, int[] mista, int[] minne, int[] hinta)

Parametri n on kaupunkien määrä, kokonaisluku välillä 1..105. Kaupungit on numeroitu tuttuun tapaan kokonaisluvuin 1..n.

Taulukot mista, minne ja hinta kuvaavat tieverkoston tiet. Taulukko mista kertoo, mistä kaupungista tie alkaa, ja taulukko minne kertoo, mihin kaupunkiin tie päättyy. Kaikki tiet ovat kaksisuuntaisia, ja niiden määrä on välillä 0..105. Lisäksi taulukko hinta kertoo, paljonko tien kunnostaminen maksaisi. Jokainen hinta on kokonaisluku välillä 1..109.

Metodin tulee palauttaa pienin kokonaiskustannus, jolla teitä saadaan korjattua siinä määrin, että minkä tahansa kaupunkiparin välillä pääsee kulkemaan korjattujen teiden kautta.

Esimerkit

# metodin kutsu haluttu palautusarvo
1 kunnostus(3, new int[] {1, 2}, new int[] {2, 3}, new int[] {7, 4}) 11
2 kunnostus(3, new int[] {1, 2, 1}, new int[] {2, 3, 3}, new int[] {7, 4, 5}) 9
3 kunnostus(3, new int[] {1, 2, 1}, new int[] {2, 3, 3}, new int[] {2, 2, 2}) 4

Tehtävä 3

Myös käännöstoimistossa joudutaan tekemään säästöjä. Tällä hetkellä palveluksessa on joukko kääntäjiä, joista jokainen kääntää kahden kielen välillä. Käännöstoimisto on siitä erikoinen, että jokainen kääntäjä pystyy kääntämään kahteen suuntaan (yleensä kääntäjät kääntävät vain äidinkielelleen). Osa kääntäjistä saattaa olla kuitenkin turhia.

Oletetaan esimerkiksi, että palveluksessa ovat seuraavat kääntäjät:

kääntäjä kielipari palkka
1 saksa–suomi 5000
2 ruotsi–suomi 9000
3 kiina–saksa 2500
4 suomi–kiina 2000

Nyt kääntäjä 1 kannattaa erottaa, koska käännöksen saksan ja suomen välillä voi tehdä myös halvemmin kiinan kautta kääntäjien 3 ja 4 avulla. Kääntäjä 2 taas on korvaamaton, koska kukaan muu ei osaa ruotsia, joten hänet on pakko säilyttää palveluksessa korkeasta palkasta huolimatta.

Toteutus

Toteuta metodi: long kaannokset(String[] mista, String[] minne, int[] hinta)

Taulukot mista ja minne kertovat, minkä kieliparin välillä kukin kääntäjä pystyy kääntämään. Taulukko hinta kertoo, paljonko kääntäjälle täytyy maksaa palkkaa. Kääntäjien määrä on välillä 1..105.

Metodin tulee palauttaa pienin kokonaiskustannus, jolla käännöstoimisto pystyy kääntämään edelleen kaikkien samojen kielten välillä kuin ennenkin.

Esimerkit

# metodin kutsu haluttu palautusarvo
1 kaannokset(new String[] {"suomi", "ruotsi"}, new String[] {"ruotsi", "englanti"}, new int[] {7, 4} 11
2 kaannokset(new String[] {"suomi", "ruotsi"}, new String[] {"saksa", "englanti"}, new int[] {5, 5} 10
3 kaannokset(new String[] {"suomi", "ruotsi", "suomi"}, new String[] {"ruotsi", "englanti", "englanti"}, new int[] {7, 4, 5} 9
4 kaannokset(new String[] {"suomi", "suomi"}, new String[] {"ruotsi", "ruotsi"}, new int[] {2, 3} 2

Tehtävä 4

Sinulle on annettu tiedot rautaverkostosta, joka muodostuu kaupungeista ja niiden välisistä radoista. Jokaisesta rataosuudesta tiedetään myös, mikä on maksimipaino siinä ajavalle junalle. Kuinka painavan junan voit hankkia, jos haluat pystyä matkustamaan sillä minkä tahansa kaupunkiparin välillä?

Toteutus

Toteuta metodi: int suurinJuna(int n, int[] mista, int[] minne, int[] raja)

Parametri n on kaupunkien määrä, kokonaisluku välillä 1..105. Kaupungit on numeroitu tavalliseen tapaan kokonaisluvuin 1..n.

Taulukot mista ja minne kuvaavat yhteydet kaupunkien välillä. Taulukko raja kertoo jokaisesta yhteydestä junan maksimipainon. Yhteyksien määrä on välillä 0..105.

Metodin tulee palauttaa raskain juna, jolla pystyy ajamaan minkä tahansa kaupunkiparin välillä. Voit olettaa, että rataverkko kattaa kaikki kaupungit.

Esimerkit

# metodin kutsu haluttu palautusarvo
1 suurinJuna(3, new int[] {1, 2}, new int[] {2, 3}, new int[] {7, 4}) 4
2 suurinJuna(3, new int[] {1, 2}, new int[] {2, 3}, new int[] {2, 2}) 2
3 suurinJuna(3, new int[] {1, 2, 1}, new int[] {2, 3, 3}, new int[] {7, 4, 5}) 5

Tehtävä 5

Jatkoa viikon 10 tehtävään 1:

Uolevin ystävät saattavat tutustua toisiinsa, mikä vaikeuttaa lahjojen jakamista. Tehtäväsi on pitää yllä tehokkaasti tietoa, voiko Uolevi jakaa lahjat haluamallaan tavalla.

Toteutus

Toteuta luokka Ystavat, joka tarjoaa seuraavat metodit:

  • Ystavat(int n): konstruktorille annetaan Uolevin ystävien määrä (välillä 1..105)
  • void lisaaYstavyys(int a, int b): henkilöt a ja b tutustuvat toisiinsa
  • boolean lahjajako(): metodin tulee kertoa, onko tällä hetkellä mahdollista jakaa lahjat

Aluksi kukaan ei tunne vielä toisiaan. Testauksessa metodeita kutsutaan korkeintaan 105 kertaa.

Esimerkit

Seuraava koodi testaa luokkaa:

Ystavat y = new Ystavat(3);
System.out.println(y.lahjajako());
y.lisaaYstavyys(1, 2);
System.out.println(y.lahjajako());
y.lisaaYstavyys(2, 3);
System.out.println(y.lahjajako());
y.lisaaYstavyys(1, 3);
System.out.println(y.lahjajako());

Koodin tulostuksen tulisi olla seuraava:

true
true
true
false