Apprentissage interactif de la théorie des graphes
Apprentissage interactif de la théorie des graphes
Guest User
Using app without sign in
Calculateur de plus courts chemins toutes paires
Plus courts chemins entre toutes paires utilisant la programmation dynamique
Sélectionnez un algorithme et générez les étapes pour commencer la visualisation
L'algorithme de Floyd-Warshall calcule les plus courts chemins entre toutes les paires de sommets d'un graphe pondéré en une seule exécution. C'est un exemple classique de programmation dynamique sur les graphes, qui accepte les poids d'arêtes négatifs tant qu'il n'y a pas de cycle négatif.
L'algorithme itère sur chaque sommet k et demande, pour chaque paire (i, j), si le chemin de i à j s'améliore en passant par k. La mise à jour dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]) est appliquée à toutes les paires, élargissant un à un l'ensemble des sommets intermédiaires autorisés. Trois boucles imbriquées sur les sommets donnent O(V au cube) temps et O(V au carré) espace, praticable pour des graphes denses jusqu'à quelques milliers de nœuds.
Floyd-Warshall répond aux requêtes de distance entre toutes les paires en planification d'itinéraires, calcule la fermeture transitive de relations, trouve les diamètres de graphes et gère la détection d'arbitrage sur toutes les paires de devises à la fois. C'est un sujet d'entretien apprécié pour tester l'intuition de la programmation dynamique sur les graphes.
Trois boucles imbriquées et une seule ligne de mise à jour. Toute la subtilité réside dans l'ordre des boucles: k doit être la boucle la plus externe, et se tromper là-dessus est le bogue classique.
FloydWarshall(graphe):
dist = matrice V par V, tout a l infini
pour chaque sommet v: dist[v][v] = 0
pour chaque arete (u,v,w): dist[u][v] = w
pour k dans sommets: // intermediaire
pour i dans sommets: // source
pour j dans sommets: // cible
si dist[i][k] + dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
suiv[i][j] = suiv[i][k] // reconstruction
// Cycle negatif ssi dist[v][v] < 0 pour un vL'invariant est qu'après l'itération pour k, dist[i][j] est le plus court chemin de i à j n'utilisant que les k premiers sommets comme intermédiaires. Il faut que k soit la boucle externe pour que cela tienne: c'est elle qui élargit d'un cran à la fois l'ensemble des escales autorisées. Placer k à l'intérieur termine tout de même et produit des nombres plausibles, ce qui rend précisément ce bogue si difficile à repérer.
Exécute Floyd-Warshall sur un petit graphe orienté et observe une entrée s'améliorer deux fois à mesure que l'ensemble des intermédiaires autorisés grandit.
Graphe d'exemple: Arêtes orientées A vers B (3), A vers C (8), B vers C (2), B vers D (7) et C vers D (1).
Les distances finales depuis A sont B 3, C 5, D 6. L'entrée A vers D s'est améliorée deux fois, de l'infini à 10 puis à 6, ce qui montre directement la stratification: la passe k = C n'a pu trouver la meilleure route que parce que la passe k = B avait déjà amélioré A vers C. Cette dépendance est la raison pour laquelle k doit être la boucle externe.
Temps: O(V^3) · Espace: O(V^2)
Trois boucles imbriquées sur tous les sommets donnent exactement V au cube itérations, chacune effectuant un travail constant. Il n'y a ni sortie anticipée ni dépendance au nombre d'arêtes, l'algorithme coûte donc autant sur un graphe creux que sur un graphe dense. L'espace est la matrice V par V des distances, plus une seconde matrice si tu veux reconstruire les chemins et pas seulement leurs longueurs. En pratique V au cube reste acceptable jusqu'à quelques milliers de sommets; à 5 000 cela représente 125 milliards d'opérations, et lancer Dijkstra depuis chaque sommet, en O(V·E·log V), devient le meilleur choix sur les graphes creux.
Floyd-Warshall l'emporte sur la densité et la simplicité, et perd nettement sur les grands graphes creux.
| Alternative | À préférer quand | Coût |
|---|---|---|
| Dijkstra depuis chaque sommet | Graphe creux, sans poids négatif. Bien plus rapide quand E est très inférieur à V au carré. | O(V·E·log V) |
| Algorithme de Johnson | Graphe creux avec poids négatifs. Repondère avec Bellman-Ford puis lance Dijkstra depuis chaque sommet. | O(V·E + V^2·log V) |
| BFS depuis chaque sommet | Le graphe est non pondéré, tu ne veux donc que les nombres de sauts entre toutes les paires. | O(V·(V + E)) |
| Fermeture transitive | Tu ne veux que l'atteignabilité, pas la distance. La même triple boucle avec un OU booléen, soit l'algorithme original de Warshall. | O(V^3) |
Lire l'article complet: Shortest Path Algorithms Explained
Algorithmes associés: Algorithme de Dijkstra, Algorithme de Bellman-Ford