Floyd-Warshall: Korteste veje mellem alle par
Udfyld afstandsmatricen mellem alle par med Floyd-Warshall-algoritmen med tre indlejrede løkker, og anvend den til at finde det mindste antal hop mellem alle nodepar.
Floyd-Warshall: Korteste veje mellem alle par er en gratis Forberedelse til kodeinterviews-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Forberedelse til kodeinterviews, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Forberedelse til kodeinterviews-kurset indeholder 4 lektioner i alt.
Korteste stier mellem alle nodepar
Floyd-Warshall beregner korteste stier mellem alle par af noder i en vægtet graf — inklusive grafer med negative kantvægte (men ikke negative cyklusser). At køre Dijkstra fra hver kilde tager O(V × (V+E) log V); Floyd-Warshall kører i O(V³)
Den grundlæggende idé: Mellemliggende noder
Floyd-Warshalls indsigt: dp[i][j][k] = den korteste sti fra i til j, hvor kun noderne {0, 1, ..., k} bruges som mellemled. Enten bruger den korteste sti node k som mellemled, eller også gør den ikke. Hvis den gør: dp[i][j][k] = dp[i][k][k-1] + dp[k][j][k-1]. Hvis ikke: dp[i][j][k] = dp[i][j][k-1]. Da den tredje dimension kun bevæger sig fremad, kan den elimineres — vi opdaterer direkte.
Initialisering af afstandsmatricen
Start med en V×V-matrice: dist[i][i] = 0 (afstand fra en node til sig selv er nul), dist[i][j] = weight for direkte kanter og dist[i][j] = inf for par uden kanter. Gennemløb derefter alle mellemliggende noder k, og opdatér parrene (i, j). Den ydre løkke over k skal komme først, så vi korrekt opbygger stier gennem et stadigt større sæt af tilladte mellemled.
def floyd_warshall(V, edges):
INF = float('inf')
dist = [[INF]*V for _ in range(V)]
for i in range(V):
dist[i][i] = 0
for u, v, w in edges:
dist[u][v] = w # directed graph
for k in range(V): # intermediate node
for i in range(V):
for j in range(V):
if dist[i][k] + dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
return distKomplet implementering med eksempel
Lad os gennemgå Floyd-Warshall på en graf med 4 noder. Efter behandling af hver mellemliggende node k udfyldes matricen med kortere stier, der går gennem node k. Algoritmen håndterer naturligt flere kanter ved gradvist at opbygge de korteste stier.
def floyd_warshall(V, edges):
INF = float('inf')
dist = [[INF]*V for _ in range(V)]
for i in range(V):
dist[i][i] = 0
for u, v, w in edges:
dist[u][v] = w
for k in range(V):
for i in range(V):
for j in range(V):
if dist[i][k] != INF and dist[k][j] != INF:
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
return dist
V = 4
edges = [(0,1,3),(0,2,7),(1,2,1),(1,3,5),(2,3,2)]
dist = floyd_warshall(V, edges)
for row in dist:
print([x if x != float('inf') else 'INF' for x in row])Registrering af negative cyklusser
Efter Floyd-Warshall er kørt, skal du kontrollere hoveddiagonalen: Hvis en dist[i][i] < 0, findes der en negativ cyklus, der går gennem node i. Det skyldes, at en negativ cyklus gør det muligt at nå i fra i med negativ omkostning. Hvis der ikke findes en negativ cyklus, forbliver alle diagonale elementer 0.
def has_negative_cycle_fw(V, edges):
dist = floyd_warshall(V, edges)
for i in range(V):
if dist[i][i] < 0:
return True # negative cycle through node i
return False
# Negative cycle: 0->1->2->0 with weights 1,-3,1 (sum=-1)
edges_neg = [(0,1,1),(1,2,-3),(2,0,1)]
print(has_negative_cycle_fw(3, edges_neg)) # TrueGenskabelse af stien
For at genskabe den faktiske sti fra i til j skal du vedligeholde en next[i][j]-matrix: Oprindeligt er next[i][j] = j for direkte kanter. Ved en opdatering via den mellemliggende node k skal du sætte next[i][j] = next[i][k]. For at genskabe stien skal du starte ved i og følge next-pegerne, indtil du når j. Det tilføjer O(V²) plads og O(V) pr. stigenskabelse.
def fw_with_path(V, edges):
INF = float('inf')
dist = [[INF]*V for _ in range(V)]
nxt = [[None]*V for _ in range(V)]
for i in range(V): dist[i][i] = 0
for u, v, w in edges:
dist[u][v] = w; nxt[u][v] = v
for k in range(V):
for i in range(V):
for j in range(V):
if dist[i][k] + dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
nxt[i][j] = nxt[i][k]
return dist, nxt
def get_path(nxt, i, j):
if nxt[i][j] is None: return []
path = [i]
while i != j:
i = nxt[i][j]; path.append(i)
return pathTransitiv lukning
En enklere variant: transitiv lukning besvarer spørgsmålet 'kan node j nås fra node i?' for alle par. Erstat afstande med booleske værdier: reach[i][j] = reach[i][j] or (reach[i][k] and reach[k][j]). Dette er Floyd-Warshall med boolesk OR i stedet for addition og min. Initialisér reach[i][i] = True og reach[i][j] = True for direkte kanter.
def transitive_closure(V, edges):
reach = [[False]*V for _ in range(V)]
for i in range(V):
reach[i][i] = True
for u, v, _ in edges:
reach[u][v] = True
for k in range(V):
for i in range(V):
for j in range(V):
reach[i][j] = reach[i][j] or (reach[i][k] and reach[k][j])
return reach
edges = [(0,1,1),(1,2,1)]
R = transitive_closure(3, edges)
print(R[0][2]) # True (0 can reach 2 via 0->1->2)Kompleksitet og hvornår den skal bruges
Floyd-Warshall: O(V³)-tid, O(V²)-plads. For tætte grafer (E ≈ V²) med V ≤ 300 er dette hurtigere end at køre Dijkstra V gange (også O(V³) i det tilfælde). For sparsomme grafer med V = 1000 og E = 3000 koster V Dijkstra-kørsler O(V×E×log V) ≈ 33M, mens Floyd-Warshall koster O(V³) = 10⁹ — Dijkstra vinder. Du skal vide, hvornår hver algoritme er passende.
Mindste antal hop mellem alle par
Sæt alle kantvægte til 1 (eller brug en boolesk nabomatrix med Floyd-Warshall, hvor du bruger addition i stedet for min): dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]). Dette beregner det mindste antal hop mellem alle par — det samme resultat som BFS mellem alle par, men beregnet med ét O(V³)-gennemløb med Floyd-Warshall.
def min_hops_all_pairs(V, adj_list):
INF = float('inf')
dist = [[INF]*V for _ in range(V)]
for i in range(V):
dist[i][i] = 0
for j in adj_list[i]:
dist[i][j] = 1
for k in range(V):
for i in range(V):
for j in range(V):
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
return dist
adj = [[1,2],[2],[3],[],[]]
print(min_hops_all_pairs(5, adj)[0]) # [0, 1, 1, 2, INF]Interviewkontekst: Når interviewere spørger om Floyd-Warshall
Floyd-Warshall dukker op i interviews om opgaver, der handler om: (1) afstande mellem alle par i en lille graf, (2) at finde ud af, om der findes en cyklus med negativ samlet vægt, (3) at beregne korteste veje i problemer med begrænsningsudbredelse og (4) opgaver, der udtrykkeligt beder om løsninger i O(V³), hvor V ≤ 200. Nævn altid strukturen med tre løkker og kravet om, at der ikke må være negative cyklusser, for at algoritmen er korrekt.
Urettede grafer med Floyd-Warshall
For urettede grafer skal du tilføje begge retninger for hver kant: dist[u][v] = dist[v][u] = weight. Resten af algoritmen er identisk. Den resulterende matrix er symmetrisk: dist[i][j] == dist[j][i] for alle par. Vær forsigtig under initialiseringen, så du ikke ved en fejl tildeler retningsbestemte kanter — urettede kanter skal tilføjes i begge retninger til den indledende matrix, før de tre løkker køres.
def fw_undirected(V, edges):
INF = float('inf')
dist = [[INF]*V for _ in range(V)]
for i in range(V): dist[i][i] = 0
for u, v, w in edges:
dist[u][v] = w
dist[v][u] = w # both directions for undirected
for k in range(V):
for i in range(V):
for j in range(V):
if dist[i][k] + dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
return distHurtigt tjek
Afprøv din forståelse af begreberne fra Data Structures & Algorithms — Coding Interview Prep i denne lektion.
Opsummering af lektionen
I denne lektion har du lært: Floyd-Warshall beregner de korteste veje mellem alle par med tre indlejrede løkker og rekurrensen dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]), negative cyklusser kan registreres ved at kontrollere, om en dist[i][i] < 0 efter afslutningen, og algoritmen kører i O(V³)-tid og bruger O(V²)-plads. Næste gang genbesøger vi anvendelser af korteste veje med Network Delay Time og teknikker til rekonstruktion af veje.
Lær Forberedelse til kodeinterviews med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 90
- Lektioner
- 360
Ofte stillede spørgsmål
Er lektionen “Floyd-Warshall: Korteste veje mellem alle par” gratis?
Ja — hele teksten til “Floyd-Warshall: Korteste veje mellem alle par” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Forberedelse til kodeinterviews-kurset, skal du opgradere til CoddyKit PRO. Forberedelse til kodeinterviews-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Floyd-Warshall: Korteste veje mellem alle par”?
Udfyld afstandsmatricen mellem alle par med Floyd-Warshall-algoritmen med tre indlejrede løkker, og anvend den til at finde det mindste antal hop mellem alle nodepar. Du øver dig i Forberedelse til kodeinterviews med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Forberedelse til kodeinterviews?
Der kræves ingen tidligere erfaring. Forberedelse til kodeinterviews på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Floyd-Warshall: Korteste veje mellem alle par”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Forberedelse til kodeinterviews-lektion?
Ja. Alle Forberedelse til kodeinterviews-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Dijkstras algoritme med en prioritetskø
- Bellman-Ford og negative cykler
- Floyd-Warshall: Korteste veje mellem alle par
- Netværksforsinkelse og rekonstruktion af sti