Dijkstra qui rend les chemins
Exercice · niveau 2 · mathématiques appliquées (ECG 1re année), chapitre 11 — Informatique et algorithmique · Graphes et plus courts chemins
Énoncé
Modifier dijkstra pour qu'elle renvoie aussi, pour chaque sommet, le chemin complet depuis la source. (Mémoriser le prédécesseur à chaque mise à jour.)
Corrigé
def dijkstra(G, source):
# G[u] = liste de couples (voisin, poids), poids POSITIFS
INF = float('inf')
dist = {u: INF for u in G}
pred = {u: None for u in G}
dist[source] = 0
restants = set(G)
while restants:
u = min(restants, key=lambda s: dist[s])
if dist[u] == INF:
break # les sommets restants sont inatteignables
restants.remove(u)
for v, poids in G[u]:
if dist[u] + poids < dist[v]:
dist[v] = dist[u] + poids
pred[v] = u # <- la seule ligne ajoutee
return dist, pred
def chemin(pred, source, cible):
c = []
u = cible
while u is not None:
c.append(u)
u = pred[u]
c.reverse()
return c if c[0] == source else None # None : pas de chemin
Le principe. Une seule ligne suffit : chaque fois qu'on améliore la distance d'un sommet, on note par où l'on est passé. À la fin, remonter les prédécesseurs depuis la cible reconstitue le chemin — à l'envers, d'où le reverse.
Deux garde-fous. Le test c[0] == source distingue « pas de chemin » d'un chemin réel : sans lui, la fonction renverrait une liste tronquée pour un sommet inatteignable. Et l'arrêt sur dist[u] == INF évite de traiter des sommets qu'aucune arête ne relie à la source.
L'hypothèse, toujours la même : les poids doivent être positifs. Avec un poids négatif, un sommet déjà « fixé » pourrait être amélioré plus tard, et le prédécesseur mémorisé deviendrait faux.
Les autres exercices de ce chapitre Le cours du chapitre
Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.