Compter les chemins hamiltoniens, avec la grille complète
Exercice · niveau 2 · informatique (MP2I/MPI), chapitre 14 — Exploration exhaustive et retour sur trace
Énoncé
Écrire une fonction qui compte les chemins passant une fois et une seule par chacun des sommets d'un graphe, à partir d'un sommet donné. Donner spécification, terminaison, correction, complexité.
Corrigé
(* Nombre de chemins hamiltoniens de g partant du sommet depart.
Précondition : g est une matrice d'adjacence n x n, 0 <= depart < n.
Postcondition : le résultat est compris entre 0 et (n-1)!.
Complexité : O(n!) au pire, O(n) en espace (le tableau vu et la pile). *)
let chemins_hamiltoniens g depart =
let n = Array.length g in
let vu = Array.make n false in
let total = ref 0 in
(* INVARIANT : vu.(s) est vrai exactement pour les sommets du chemin courant,
lequel compte k sommets et finit en courant. *)
let rec explorer courant k =
if k = n then incr total
else
for s = 0 to n - 1 do
if g.(courant).(s) && not vu.(s) then begin
vu.(s) <- true;
explorer s (k + 1);
vu.(s) <- false (* on DÉFAIT *)
end
done
in
vu.(depart) <- true;
explorer depart 1;
!total
Terminaison. Variant : , le nombre de sommets restant à visiter. Chaque appel récursif se fait avec , donc le variant décroît strictement de et reste positif ou nul. La profondeur est bornée par .
Correction. L'invariant est rétabli à chaque retour par la ligne qui défait : sans elle, ne décrirait plus le chemin courant mais l'union de tous les chemins déjà essayés, et le compte serait faux — c'est exactement l'exercice 14.3. À la sortie, on a compté une fois chaque suite de sommets deux à deux distincts, reliés consécutivement, commençant en depart : c'est la définition d'un chemin hamiltonien.
Complexité. L'arbre de recherche a au plus feuilles : à chaque étage, un sommet de moins est disponible. Sur un graphe complet, cette borne est atteinte. Le graphe complet à sommets a donc chemins hamiltoniens depuis un sommet donné, et son arbre de recherche compte nœuds — mesuré au problème 14.5.
Et il n'y a pas mieux. Décider si un graphe possède un chemin hamiltonien est np-complet (chapitre chap:decidabilite). Le retour sur trace n'est donc pas un pis-aller : c'est, à ce jour, ce que l'on sait faire.
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.