5.2 Ford-Fulkerson, Edmonds-Karp og maks-flyt/min-snitt
`Ford-Fulkerson`-metoden, `Edmonds-Karp` (BFS-forøkende stier), maks-flyt/min-snitt-teoremet, og hvorfor FF er pseudopolynomisk mens EK er polynomisk.
Grunnlaget er de 17 settene fra august 2015 til august 2023 som er gjennomgått
tema for tema — det er nevneren hver gang boka oppgir en prosent.
Maks-flyt er den ene av fagets to designryggrader: de åpne designoppgavene på
slutten av settet handler oftere om flyt enn om noe annet. Prioritet:
høyeste prioritet — dette må sitte.
Tre sjangre henter fra dette kapitlet, og de skrives ut i klarspråk her:
- Sjanger E — kjøretidskunnskap, altså at du oppgir kjøretiden i det
strammeste uttrykket som er riktig. for Edmonds-Karp er et av
tallene som skal sitte kaldt.
- Sjanger F — «stemmer dette?», altså at du svarer ja eller nei først og
deretter gir én presis setning. Den klassiske her: «Er Ford-Fulkerson
polynomisk?»
- Sjanger G — argument om vanskelighet, altså at du sier hva et argument
faktisk viser. Her møter du skillet mellom pseudopolynomisk og
NP-hardt, som er et av fagets faste innsiktsspørsmål.
Det ene skillet du må ha klart: at Ford-Fulkerson ikke er polynomisk,
betyr ikke at maks-flyt er et vanskelig problem. Maks-flyt løses i
polynomisk tid av Edmonds-Karp. Det er algoritmen som er treg, ikke problemet
som er hardt. Dette er felle #7.
Slik er kapitlet lagt opp (55 min):
| Innhold | Tid |
|---|---|
| Ford-Fulkerson-metoden | ca. 15 min |
Edmonds-Karp og hvorfor den er polynomisk | ca. 12 min |
| Maks-flyt/min-snitt-teoremet | ca. 14 min |
| Pseudopolynomisk mot polynomisk | ca. 14 min |
Forkunnskaper
- kap. 5.1 — flytnett, restnett og snitt. Dette er
hele grunnlaget, og de fire resultatene du trenger i hånden, står her:
1. Restkapasiteten er for en framoverkant,
og for ryggkanten. Restnettet inneholder
alle kanter med .
2. En forøkende sti er en sti fra til i restnettet.
Flaskehalsen er den minste restkapasiteten på stien.
3. Et snitt deler nodene med og .
Snittkapasiteten teller bare kantene som går fra til .
4. Snittlemmaet: for enhver lovlig flyt og ethvert snitt er
. All flyt må krysse ethvert snitt.
Det siste er den ene ulikheten hele dette kapitlet hviler på.
- kap. 4.1 — BFS. Edmonds-Karp er Ford-Fulkerson
med BFS til å finne stien, og det er den eneste forskjellen.
- kap. 1.1 — de asymptotiske symbolene.
Ford-Fulkerson-metoden (~15 min)
Ideen er så enkel at det er lett å undervurdere den: så lenge det finnes en
vei å presse mer vann gjennom, gjør det.
«En vei» betyr en sti fra til i restnettet, og restnettet er nettopp
konstruert slik at en sti der alltid er lovlig å bruke. Ryggkantene gjør at
metoden kan angre tidligere valg: å sende flyt bakover langs en ryggkant
betyr i praksis å trekke tilbake litt av det som ble sendt framover før.
Legg merke til ordet metode, ikke algoritme. Ford-Fulkerson sier ikke
hvordan stien skal finnes — bare at den skal finnes. Det valget er det som
avgjør kjøretiden, og det er derfor Edmonds-Karp finnes.
s, slukt og kapasiteter c(u,v) >= 0. Restnettet G_f bygges av c og f etterregelen fra kap. 5.1. Kapasitetene antas heltallige
— ellers er ikke terminering garantert.
Prebetingelse: c(u,v) >= 0 for alle kanter.
Postbetingelse: f er en maksimal flyt, og nodene som kan nås fra s i
restnettet, utgjør venstresiden i et min-snitt.
Ford-Fulkerson(G, s, t)
Input: flytnettet G med kapasiteter c, kilde s, sluk t
Output: en maksimal flyt f
for hver kant (u,v) i E
f(u,v) = 0
while det finnes en sti p fra s til t i restnettet G_f
flaskehals = min over kantene (u,v) paa p av c_f(u,v)
for hver kant (u,v) paa p
if (u,v) er en framoverkant
f(u,v) = f(u,v) + flaskehals
else
f(v,u) = f(v,u) - flaskehals
return f
Kjoeretid: O(E * |f*|) med heltallige kapasiteterInvarianten i én setning: f er hele veien en lovlig flyt — den bryter
verken kapasitets- eller bevaringsbetingelsen — og flytverdien øker med minst 1
i hver runde.
Hvorfor den terminerer. Med heltallige kapasiteter er flaskehalsen alltid
et positivt heltall, så øker med minst 1 per runde. Den kan
ikke overstige maksimal flytverdi , så antall runder er høyst
. Hver runde koster til å finne stien og forøke.
Kjøretid: . Legg merke til hva som står der:
kjøretiden avhenger av tallverdien til svaret, ikke bare av hvor stor
grafen er. Det er nettopp definisjonen på pseudopolynomisk, og vi kommer
tilbake til det.
Vanningsanlegget fra kap. 5.1 har pumpehuset ,
kummene , , , og jordet , med kapasitetene
c(s,a) = 12 c(s,b) = 9 c(a,b) = 4 c(a,c) = 8
c(b,d) = 10 c(c,t) = 14 c(d,c) = 5 c(d,t) = 9Kjør Ford-Fulkerson fra nullflyten, og finn stiene med BFS (altsåEdmonds-Karp). Naboene besøkes i alfabetisk rekkefølge.
Oppgi maksimal flytverdi og et min-snitt.
| Runde | Forøkende sti | Flaskehals | etterpå |
|---|---|---|---|
| 1 | 8 | 8 | |
| 2 | 9 | 17 | |
| 3 | 1 | 18 | |
| 4 | ingen sti finnes i | — | 18 |
Runde 1: stien har restkapasiteter , og
— flaskehalsen er 8, satt av den mettede kanten .
Runde 2: stien har restkapasiteter , og —
flaskehalsen er 9.
Runde 3: nå er de to åpenbare veiene brukt opp, og
BFS finner med restkapasiteter , , , og
. Flaskehalsen er 1, satt av , som allerede bærer 9 av 10.
Runde 4: BFS fra i restnettet når bare og . Ingen sti til
finnes, og algoritmen stopper.
Den endelige flyten:
f(s,a) = 9/12 f(s,b) = 9/9 f(a,b) = 1/4 f(a,c) = 8/8
f(b,d) = 10/10 f(c,t) = 9/14 f(d,c) = 1/5 f(d,t) = 9/9Sluttilstanden — det du ville levert på eksamen:Maks-flyt . Et min-snitt er
, ,
med snittkapasitet .
Slik leser du av min-snittet. Når algoritmen stopper, kjører du én siste
BFS fra i restnettet. Nodene den når, utgjør ; resten utgjør . Her
nås og , men ikke , eller .
Legg merke til at runde 3 var den vanskelige. Uten ryggkantene i restnettet
ville den stien ikke eksistert — kanten er en vanlig framoverkant her,
men det er sidesprangene gjennom som gjør at den siste enheten finner
veien. En sti som denne er nettopp det håndkjøringsoppgaver tester.
Merk at oppgaven ba om både flytverdien og et min-snitt. Er begge spurt om,
er begge en del av svaret.
(Innstegsoppgave, sjanger D — definisjon med egne ord, altså én presis setning
med hovedpoenget først.)
Forklar hva Ford-Fulkerson-metoden gjør, og hvorfor den kalles en metode
og ikke en algoritme.
Et flytnett har nodene , , , , , og kapasitetene
c(s,u) = 10 c(s,v) = 8 c(u,v) = 3 c(u,x) = 6
c(v,y) = 9 c(x,t) = 7 c(y,x) = 4 c(y,t) = 5Kjør Edmonds-Karp fra nullflyten, med naboene i alfabetisk rekkefølge.
a) Oppgi de forøkende stiene og flaskehalsene.
b) Oppgi maksimal flytverdi og et min-snitt.
Edmonds-Karp og hvorfor den er polynomisk (~12 min)
Forskjellen mellom Ford-Fulkerson og Edmonds-Karp er én linje: hvordan
stien velges. Edmonds-Karp bruker korteste forøkende sti, målt i antall
kanter, og finner den med BFS.
Det høres ut som en detalj. Det er det ikke.
Ford-Fulkerson. Restnettet bygges på nytt (eller oppdateres) etter hver forøkning, og
BFS kjøres på det.Prebetingelse: c(u,v) >= 0. Merk at heltallighet ikke er nødvendig
her — kjøretidsgrensen holder også for reelle kapasiteter.
Postbetingelse: f er en maksimal flyt.
Edmonds-Karp(G, s, t)
Input: flytnettet G med kapasiteter c, kilde s, sluk t
Output: en maksimal flyt f
for hver kant (u,v) i E
f(u,v) = 0
while BFS finner en sti p fra s til t i G_f
flaskehals = min over kantene (u,v) paa p av c_f(u,v)
forok flyten langs p med flaskehals
return f
Kjoeretid: O(V * E^2)Grunnideen i én setning: når stien alltid er den korteste, kan avstanden
fra til hver node i restnettet aldri synke underveis — og det gir en
grense på hvor mange forøkninger som kan gjøres.
Utledningen, i tre ledd.
Ledd 1. Avstanden fra til i restnettet er
ikke-synkende gjennom hele kjøringen. Hver forøkning fjerner minst én kant fra
restnettet (den som var flaskehals) og kan legge til ryggkanter, men aldri på
en måte som forkorter avstanden.
Intuisjon: BFS tar alltid den korteste veien, så en ny snarvei måtte ha
eksistert allerede.
Ledd 2. En kant som er flaskehals i én runde, kan ikke bli flaskehals
igjen før avstanden har økt med minst 2.
Intuisjon: kanten forsvinner fra restnettet når den mettes, og den kommer
bare tilbake hvis flyt sendes bakover gjennom den — og det skjer bare når
ligger lenger unna enn før.
Ledd 3. Avstanden er høyst , så hver av de kantene kan være
flaskehals høyst ganger. Det gir forøkninger totalt, og hver
koster til BFS.
Kjøretid: . Uttrykket inneholder bare og — ingen
kapasiteter. Det er nettopp det som gjør algoritmen polynomisk.
Edmonds-Karp, og hva avhenger den av?b) Hva er kjøretiden til
Ford-Fulkerson med vilkårlig valg av sti, og hvaavhenger den av?
c) Hvilken av de to ville du valgt hvis kapasitetene kunne være opptil en
milliard?
Maks-flyt/min-snitt-teoremet (~14 min)
Nå kommer resultatet hele delen bygger mot, og det er et av de vakreste i
faget: det største du kan presse gjennom, er nøyaktig like mye som den
billigste flaskehalsen.
ekvivalente:
1. er en maksimal flyt.
2. Restnettet inneholder ingen forøkende sti.
3. Det finnes et snitt med .
Følgen er navnet på teoremet: den maksimale flytverdien er lik den minimale
snittkapasiteten,
Argumentet, kort. At 1 gir 2 er lett: fantes det en forøkende sti, kunne
flyten økes, og da var den ikke maksimal. At 3 gir 1 følger av snittlemmaet fra
kap. 5.1: enhver flyt er , så en flyt som
når , kan ikke slås.
Den interessante retningen er at 2 gir 3, og den er konstruktiv: la være
nodene som kan nås fra i restnettet. Siden ingen forøkende sti finnes, er
, så er et snitt. Hver kant fra til må være
mettet — ellers ville den gitt en restkant, og naboen ville ligget i .
Hver kant fra til må ha null flyt, av samme grunn. Da er
.
Konsekvensen du bruker på eksamen: når Ford-Fulkerson stopper, kjør énBFS fra i restnettet. Nodene den når, er venstresiden i et min-snitt.
Du får snittet gratis, og du får samtidig beviset på at flyten er maksimal.
En kandidat leverer en flyt med verdi 18 i vanningsanlegget og påstår at den er
maksimal.
a) Hvordan kan påstanden bevises uten å kjøre algoritmen på nytt?
b) Gjennomfør beviset.
c) Hva ville et snitt med kapasitet 22 fortalt deg?
for ethvert snitt, så en flyt som når kapasiteten til et snitt,
kan ikke slås — og snittet kan ikke være dyrere enn noe annet.
Det er den ene retningen av maks-flyt/min-snitt, og den er kort nok til å
skrives på to linjer.
b) Velg og . Kantene fra til er
med kapasitet 8 og med kapasitet 10. Ingen andre kanter går
den veien.
Altså er flyten maksimal, og snittet er minimalt. Ferdig.
c) Ingenting avgjørende. Et snitt med kapasitet 22 gir bare den øvre
grensen , og den er allerede oppfylt av en flyt på 18.
Beviset krever et snitt som treffer flytverdien.
Snittet har for eksempel kapasitet — sant, men
ubrukelig som bevis.
Svarformen på eksamen: oppgi snittet, list kantene som krysser, summer, og
konstater likheten. Fire linjer.
Ta stilling til hver av påstandene:
a) Et flytnett har alltid nøyaktig ett min-snitt.
b) Hvis en kant krysser et min-snitt fra til , må den være mettet.
c) Maks-flyt/min-snitt-teoremet gjelder bare når kapasitetene er heltall.
Pseudopolynomisk mot polynomisk (~14 min)
Her ligger et av fagets faste innsiktsskiller, og det er verdt å bruke tid på —
fordi det blir hentet fram igjen i kap. 7.2 og fordi
det er lett å trekke feil konklusjon av det.
en algoritme er pseudopolynomisk når kjøretiden er polynomisk i
tallverdiene i inputen, men ikke i inputens lengde.
Ford-Fulkerson er . Skriver du en kapasitet på
, tar det bare 30 binære siffer å skrive den ned — men den kan gi en
milliard runder. Kjøretiden vokser altså eksponentielt i antall siffer.
En polynomisk algoritme har kjøretid som er polynomisk i inputens lengde.Edmonds-Karp er og nevner ingen kapasiteter i det hele tatt — den
er polynomisk.
Dette er felle #7, og den er blant fagets mest fremhevede.
At Ford-Fulkerson ikke er polynomisk, sier ingenting om hvor vanskelig
maks-flyt-problemet er. Det sier bare noe om den ene algoritmen.
Maks-flyt er et lett problem: Edmonds-Karp løser det i , altså i
polynomisk tid. Problemet ligger i klassen P.
Kontrollen når du skal formulere svaret:
- «Ford-Fulkerson er pseudopolynomisk» — riktig.
- «Maks-flyt er derfor et vanskelig problem» — galt.
- «Maks-flyt kan løses i polynomisk tid av Edmonds-Karp» — riktig.
Det samme skillet dukker opp igjen i kap. 6.2 med
0-1-ryggsekk, som har en -algoritme der er en tallverdi.
Der er problemet faktisk NP-hardt — men det følger ikke av at algoritmen er
pseudopolynomisk, det følger av et helt annet argument.
Konstruér et flytnett med fire noder der Ford-Fulkerson med uheldig valg
av forøkende sti bruker mange flere runder enn nødvendig, og forklar hvorforEdmonds-Karp slipper unna.
c(s,u) = 1000000 c(s,v) = 1000000
c(u,t) = 1000000 c(v,t) = 1000000
c(u,v) = 1Det uheldige valget. Velger metoden stien , er
flaskehalsen 1 — kanten slipper bare én enhet gjennom. Etter
forøkningen finnes ryggkanten med restkapasitet 1, og metoden kan
velge , som også har flaskehals 1.
Fortsetter den å veksle mellom disse to stiene, øker flyten med 1 per
runde, og det trengs 2 000 000 runder for å nå maksimal flyt.
Hvorfor Edmonds-Karp slipper unna. BFS finner alltid den korteste
stien. Stiene og har to kanter; de uheldige
stiene har tre. Edmonds-Karp tar derfor de to korte først, mestrer hele
flyten på to runder, og rører aldri kanten .
Poenget med eksemplet. Antall runder i Ford-Fulkerson avhenger av
kapasitetenes størrelse; i Edmonds-Karp avhenger det bare av grafens
form. Fordoble kapasitetene i eksemplet, og den første kjøringen tar dobbelt så
lang tid mens den andre er uendret.
Og merk hva eksemplet ikke viser: at maks-flyt er vanskelig. Det samme
nettet løses på to runder av Edmonds-Karp.
En kandidat skriver: «Ford-Fulkerson er pseudopolynomisk. Maks-flyt er derfor
et vanskelig problem, sannsynligvis NP-hardt.»
Er konklusjonen riktig? Svar ja eller nei, og forklar hva argumentet viser og
hva det ikke viser.
Et sykehus har sykepleiere og vakter. Hver sykepleier har oppgitt
hvilke vakter hun kan ta, og kan ta høyst tre vakter. Hver vakt trenger
nøyaktig én sykepleier.
Beskriv hvordan du avgjør om alle vaktene kan dekkes, og hvordan du finner en
konkret vaktliste.
De to første koster hele oppgaven.
- Å blande pseudopolynomisk og NP-hardt. Dette er felle #7. At
Ford-Fulkerson er pseudopolynomisk, sier noe om algoritmen, ikke om
problemet. Maks-flyt ligger i P.
- Å glemme ryggkantene under forøkning. En forøkende sti kan gå bakover
langs en kant som bærer flyt, og da skal flyten på den kanten senkes.
Uten ryggkantene finner metoden ikke den maksimale flyten.
- Å tro at Edmonds-Karp bare er «Ford-Fulkerson med BFS for
bekvemmelighets skyld». Kravet er at stien er den korteste; det er
nettopp det som gir .
- Å oppgi bare flytverdien når min-snittet også er spurt om. Er begge
etterspurt, er begge en del av svaret — og snittet leses gratis av
restnettet til slutt.
- Å telle kanter fra til i snittkapasiteten. Bare kantene fra
til teller. Kantene den andre veien påvirker , men ikke
.
- Å bruke et snitt med for høy kapasitet som «bevis». Beviset krever et
snitt som treffer flytverdien. Et dyrere snitt gir bare en øvre grense.
- Å tro at min-snittet er entydig. Det kan finnes flere snitt med samme
minimale kapasitet.
Og den gjennomgående: å skrive der bare er vist. Begge
kjøretidene i dette kapitlet er -grenser, ikke tette.
Kjøretidene samlet
Dette er kapitlets puggeflate. Eksamen er hjelpemiddelfri, så tabellen må ligge
i hodet.
| Algoritme | Kjøretid | Krav / egenskap |
|---|---|---|
Ford-Fulkerson (vilkårlig sti) | pseudopolynomisk; krever heltallige kapasiteter for terminering | |
Edmonds-Karp | polynomisk; krever korteste forøkende sti, funnet med BFS | |
Én BFS i restnettet | brukes både til å finne stien og til å lese av min-snittet | |
| Én forøkning langs en sti | stien har høyst kanter | |
| Å lese av min-snittet | én BFS fra etter at algoritmen har stoppet | |
Antall forøkninger i Edmonds-Karp | hver kant kan være flaskehals ganger |
Én presisering som er verdt å ta med seg. Det finnes raskere maks-flyt-
algoritmer enn
Edmonds-Karp, men de er ikke pensum her. Det du skal kunne, erat maks-flyt kan løses i polynomisk tid, og at er tallet for
Edmonds-Karp.Begrepsbank
Begrepsbanken er flashcard- og repetisjonsstoff — den gjentar det du nettopp
har lest. Hopp trygt over ved førstegangslesing; tidsanslaget for kapitlet
gjelder kjernestoffet.
starter med nullflyten og gjentar: finn en forøkende sti i restnettet, øk
flyten med flaskehalsen, gjenta til ingen sti finnes.
Kjøretid med heltallige kapasiteter.
En metode, ikke en algoritme: valget av sti er ikke spesifisert, og det er
nettopp det valget som avgjør kjøretiden.
Ford-Fulkerson der stien alltid er den korteste i restnettet, funnet medBFS.Kjøretid — polynomisk, og uavhengig av kapasitetenes størrelse.
Kravet om korteste sti er ikke valgfritt. Det er det som gir grensen på
forøkninger.
en sti fra til i restnettet .
Så lenge én finnes, kan flyten økes; når ingen finnes, er flyten maksimal.
Stien kan gå bakover langs kanter som bærer flyt — det er ryggkantene, og
de er muligheten til å angre.
den minste restkapasiteten blant kantene på en forøkende sti.
Flyten økes med nøyaktig dette tallet, og minst én kant blir mettet.
Med heltallige kapasiteter er flaskehalsen minst 1, og det er grunnen til
at metoden terminerer.
billigste snittkapasiteten.
Tre ekvivalente utsagn: flyten er maksimal, restnettet har ingen forøkende sti,
og det finnes et snitt med .
Brukes til å bevise maksimalitet: finn et snitt som treffer flytverdien, så
er saken avgjort.
når algoritmen stopper, kjør én BFS fra i restnettet. Nodene som nås,
utgjør ; resten utgjør .
Hver kant fra til er da mettet, og hver kant fra til har null
flyt.
Snittet kommer gratis — det er ingen ekstra algoritme å kjøre.
kjøretiden er polynomisk i tallverdiene i inputen, men ikke i inputens
lengde.
Ford-Fulkerson er : en kapasitet på tar 30
binære siffer å skrive, men kan gi en milliard runder.
Sier ingenting om problemets vanskelighet — det er felle #7.
kjøretiden er polynomisk i inputens lengde, altså i antall symboler som
trengs for å skrive den ned.
Edmonds-Karp er og nevner ingen tallverdier.
Et problem er «lett» hvis det finnes minst én polynomisk algoritme — ikke
hvis alle algoritmer for det er polynomiske.
å slutte fra «denne algoritmen er pseudopolynomisk» til «problemet er
vanskelig».
Ford-Fulkerson er pseudopolynomisk, men maks-flyt ligger i P fordiEdmonds-Karp er polynomisk.
Skill mellom en egenskap ved algoritmen og en egenskap ved problemet.
en kant der , altså med restkapasitet 0 framover.
Den gir ingen framoverkant i restnettet, bare en ryggkant.
Hver kant som krysser et min-snitt fra til , er mettet — det er en
del av beviset for teoremet.
restkanten med , som finnes når kanten bærer
flyt.
Å sende flyt langs den betyr å trekke tilbake flyt som ble sendt framover
før.
Uten ryggkanter finner metoden ikke maksimal flyt — det er den vanligste
håndkjøringsfeilen i flytoppgaver.
grafen med de samme nodene, og med de kantene som har .
Bygges på nytt etter hver forøkning, og inneholder både framoverkanter og
ryggkanter.
Stoppkriteriet er at ikke lenger er nåbar fra i restnettet.
summen av kapasitetene på kantene som går fra til .
Kanter som går fra til teller ikke med.
Enhver flytverdi er enhver snittkapasitet — det er snittlemmaet, og
det er derfor et snitt kan brukes som bevis.
er alle kapasitetene heltall, finnes en maksimal flyt der hver kant bærer
et heltall.
Det følger av at Ford-Fulkerson bare legger til heltallige flaskehalser.
Dette er grunnen til at flyt er et tilordningsverktøy: en kant som bærer 1,
betyr «denne tildelingen skjer».
å oversette et fordelingsproblem til et flytnett: kilde, ett nodesett for det
som skal tildeles, ett for det de tildeles til, og sluk.
Kapasiteten på kilde- og slukkantene koder øvre grenser; kantene i midten koder
hvilke tildelinger som er tillatte.
Rekonstruksjonen er å lese av hvilke midtkanter som bærer flyt.
oppgavetypen der du oppgir kjøretiden til en navngitt algoritme.
for Edmonds-Karp og forFord-Fulkerson.
Legg merke til hvilke størrelser som inngår — det er hele forskjellen
mellom polynomisk og pseudopolynomisk.
oppgavetypen der du får en påstand og skal ta stilling til den.
Svarformen er ja eller nei først, deretter én presis setning.
«Er Ford-Fulkerson polynomisk?» er den klassiske i denne delen — og
svaret er nei, med ordet pseudopolynomisk i begrunnelsen.
oppgavetypen der du skal si hva et argument faktisk viser, og hva det ikke
viser.
Svarformen er retningen, konsekvensen og det eksplisitte forbeholdet.
Her er standardfeilen å slutte fra en treg algoritme til et hardt
problem.
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.
Skolesaga er en uavhengig læringsressurs og er ikke tilknyttet eller godkjent av Norges teknisk-naturvitenskapelige universitet. Dette er ikke offisielt studiemateriell. Les mer.