Flyt er det mest allsidige grafproblemet i pensum: det kobler optimering, dualitet og reduksjoner i ett rammeverk. Mange tilsynelatende urelaterte problemer — maksimal paring, kantdisjunkte stier, prosjektutvelgelse — løses ved å oversette dem til et flytnett og kjøre én algoritme.
Flytnett, flyt og maks-flyt
Et flytnett er en rettet graf med en ikke-negativ kapasitet på hver kant, en kilde og en sluk . En flyt er en funksjon som oppfyller to krav:
Maks-flyt-problemet er å finne en lovlig flyt med størst mulig verdi . Verdien er begrenset oppad av enhver «flaskehals» i nettet — det er nettopp denne dualiteten min-snitt-teoremet gjør presis.
Restnett og forøkende stier
Gitt en flyt er ikke det interessante hvor mye som er sendt, men hvor mye mer som kan sendes. Det fanger restnettet .
Bakoverkantene er nøkkelen: de lar algoritmen ombestemme seg og dirigere flyt en bedre vei senere. En forøkende sti er en hvilken som helst sti fra til i . Langs den kan vi øke flytverdien med stiens flaskehals — den minste restkapasiteten på stien — uten å bryte verken kapasitet eller bevaring.
Maks-flyt/min-snitt-teoremet
Et snitt deler nodene slik at og . Snittets kapasitet er summen av kapasiteten på alle kanter som krysser fra til . Enhver flyt må passere et hvilket som helst snitt, så er aldri større enn kapasiteten til noe snitt. Det stramme tilfellet er hovedresultatet:
Ekvivalensen gir termineringsgarantien for algoritmene under; gir et sertifikat: når søket ikke finner flere stier, danner nodene som fortsatt er nåbare fra i den ene siden av et minimalt snitt.
Ford-Fulkerson-metoden
Ford-Fulkerson er en metode, ikke én bestemt algoritme: så lenge restnettet har en forøkende sti, finn en og forøk flyten langs den.
def ford_fulkerson(G, s, t):
for (u, v) in G.E:
f[u][v] = 0
while finnes_forøkende_sti(G_f, s, t):
p = bfs_sti(G_f, s, t)
c_f = min(restkapasitet(u, v) for (u, v) in p)
for (u, v) in p:
f[u][v] += c_f # eller opphev motgående flyt
return sum(f[s][v] for v in G.adj[s]) Interaktiv visualisering krever JavaScript.
Kanter er merket med flyt/kapasitet. Den oransje stien er forøkende; røde kanter er mettede ($f = c$). Hver runde finner en sti i restnettet og sender flaskehalsen langs den. Spill av eller stega med piltastene; nettet er det klassiske CLRS-eksemplet med maks-flyt $23$.
Hvis vi alltid velger den korteste forøkende stien (færrest kanter), målt med et BFS i restnettet, får vi Edmonds-Karp. Det er nettopp denne varianten stepperen viser. Edmonds-Karp kjører i uavhengig av kapasitetene, mens en uheldig stivalg-strategi i den rene metoden kan bruke flere forøkninger jo større tallene er.
Heltallsteoremet
Når algoritmen følger en sti og legger til flaskehalsen, holder den seg innenfor heltallene så lenge kapasitetene er heltall:
Dette er grunnen til at flyt kan modellere kombinatoriske «alt-eller-ingenting»-valg: en heltallsflyt med kapasiteter velger faktisk hele kanter eller paringer.
Reduksjoner til maks-flyt
Styrken ligger i at andre problemer kan reduseres til maks-flyt. Mønsteret er alltid det samme: bygg et flytnett der en heltalls maks-flyt koder en optimal løsning på det opprinnelige problemet.
| Problem | Konstruksjon | Maks-flyt betyr |
|---|---|---|
| Maksimal paring (todelt graf) | venstre side, kanter med kap. , høyre side | antall par i en største paring |
| Kantdisjunkte stier | alle kanter får kapasitet | antall stier fra til uten felles kant |
| Flere kilder/sluk | superkilde og supersluk med uendelig kapasitet | samlet flyt fra alle kilder |