Adloun

Probleme – Rendre le chemin, pas seulement sa longueur

Exercice · niveau 3 (difficile) · informatique (MP2I/MPI), chapitre 19 — Parcours de graphes et plus courts chemins

Énoncé

Les trois algorithmes du chapitre calculent des distances. On veut les chemins.

Corrigé

1. Le parcours en largeur avec pères.


(* Renvoie (d, pere) : d.(v) est la distance en nombre d'arcs (-1 si inaccessible)
   et pere.(v) le sommet depuis lequel v a ete decouvert (-1 pour la source
   et pour les inaccessibles).
   Precondition : 0 <= s < Array.length g.  Complexite : Theta(n + m). *)
let largeur_peres g s =
  let n = Array.length g in
  let d = Array.make n (-1) and pere = Array.make n (-1) in
  let f = Queue.create () in
  d.(s) <- 0; Queue.push s f;
  while not (Queue.is_empty f) do
    let u = Queue.pop f in
    List.iter (fun v ->
      if d.(v) = -1 then begin
        d.(v) <- d.(u) + 1;
        pere.(v) <- u;                 (* on retient QUI a decouvert v *)
        Queue.push v f
      end) g.(u)
  done;
  (d, pere)

(* Chemin de s a v, ou [] si v est inaccessible.
   Precondition : pere provient d'un parcours lance depuis s.
   Complexite : Theta(longueur du chemin). *)
let chemin pere s v =
  let rec remonter v acc =
    if v = s then s :: acc
    else if v = -1 then []             (* inaccessible : on rend la liste vide *)
    else remonter pere.(v) (v :: acc)
  in remonter v []

Mesure sur le graphe à huit sommets du premier exercice :


d    = 0 1 1 2 2 2 3 4
pere = - 0 0 1 1 2 3 6
  0 -> 3 : 0 1 3        0 -> 6 : 0 1 3 6
  0 -> 5 : 0 2 5        0 -> 7 : 0 1 3 6 7

Chaque chemin a bien arcs.

2. Les deux preuves.

C'est une arborescence. Chaque sommet accessible autre que reçoit un père une seule fois — la ligne pere.(v) &lt;- u est sous le test d.(v) = -1, qui n'est vrai qu'au premier passage. Le graphe des arcs a donc exactement arcs pour sommets accessibles. Il est de plus sans cycle : , donc la fonction décroît strictement en remontant, et une remontée ne peut pas boucler. Un graphe connexe à arcs et sans cycle est un arbre (chapitre chap:arbres).

Terminaison de chemin. Le variant est : il décroît strictement de à chaque remontée, et il est minoré par , atteint exactement en .

Le chemin est de longueur minimale. La suite a exactement arcs par la décroissance ci-dessus, et le théorème du chapitre dit que est la distance minimale. Le chemin est donc optimal — et non pas seulement « un chemin ».

3. Dijkstra et Floyd-Warshall.

Dijkstra : on écrit pere.(v) &lt;- u dans le relâchement, à côté de la mise à jour de d.(v) — et pas ailleurs. Un sommet peut changer de père plusieurs fois, la dernière valeur étant la bonne, puisque le relâchement final est celui qui a produit la distance définitive. La reconstruction est la même fonction. Mesure sur le graphe pondéré déroulé plus haut : pere = [-;0;0;2;5;2], d'où pour le sommet .

Floyd-Warshall : il n'y a pas de source, donc pas d'arborescence — il faut une matrice. On maintient , le premier sommet après sur un plus court chemin de à :


/* Initialisation : suivant[u][u] = u, suivant[u][v] = v si l'arc u->v
   existe, et -1 sinon. */
if (d[u][k] + d[k][v] < d[u][v]) {
    d[u][v] = d[u][k] + d[k][v];
    suivant[u][v] = suivant[u][k];      /* on part comme pour aller vers k */
}

/* Reconstruction : Theta(longueur du chemin). */
void afficher_chemin(int suivant[][N_MAX], int u, int v) {
    if (suivant[u][v] == -1) { printf("aucun chemin\n"); return; }
    printf("%d", u);
    while (u != v) { u = suivant[u][v]; printf(" %d", u); }
    printf("\n");
}

La ligne à comprendre est suivant[u][v] = suivant[u][k] : puisque le nouveau chemin de à commence par aller de à , son premier pas est celui du chemin de à . On stocke le premier sommet et non le dernier, ce qui donne une reconstruction dans le bon sens, sans renversement.

Le coût de la reconstruction, dans les trois cas : de mémoire par sommet (ou par couple), et à la lecture. C'est la même leçon que le chapitre chap:dynamique : on garde la décision, pas la valeur — un tableau d'entiers suffit à retrouver tous les chemins.

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.