Lycée Carnot — 2016-2017 Option informatique MP/MP*
TP 3 : Parcours de graphes et applications
Dans ce TP, on étudie deux différents parcours de graphes à l’aide d’une interface générique, et quelques-
unes de leurs applications : recherche des composantes connexes, tri topologique d’un graphe et détection
de cycles dans un graphe.
Pour traiter ce TP, il faut avoir fini les parties 2 et 3 du TP no2, puisque nous utiliserons vos implémen-
tations de graphe.
1 Piles et files
On rappelle l’interface générique d’une file ou d’une pile que vous avez implémentées au TP no1.
type ’a t;;
exception Empty;;
exception Full;;
value empty :unit -> a t;;
value is_empty :at-> bool;;
value is_full :at-> bool;;
value push :a-> at-> unit;;
value pop :at-> a;;
Si votre implémentation est douteuse, vous pouvez utiliser les modules CAML stack et queue, par
exemple :
let p=stack__new ();;
stack__push 33 p;;
stack__pop p;;
let is_empty p =stack__length p = 0;;
Attention : l’interface est légèrement différente de celle que l’on a vue en cours (et différente pour les
piles et files). Le cas des files et piles vides est géré à l’aide d’une exception. Lisez bien la documentation
des deux modules : http://caml.inria.fr/pub/docs/manual-caml-light/node15.html.
2 Parcours d’un graphe
QUESTION 1 Le pseudo-code du parcours en profondeur est donné par les algorithmes 1 et 2. Faire tourner
ces deux algorithmes à la main sur quelques exemples simples pour être sûr de bien comprendre.
QUESTION 2 On considère tout d’abord que postvisiter ne fait rien et que previsiter s imprime à
l’écran le sommet s(ici un entier). Implémenter les deux algorithmes en CAML. Vérifier que votre implé-
mentation est bien indépendante de l’implémentation de graphe sous-jacente (cela doit fonctionner aussi
bien avec une représentation par matrice d’adjacence ou par listes d’adjacence), que le graphe soit orienté
ou non. Essayer sur plusieurs exemples.
QUESTION 3 Que se passe-t-il si on inverse les rôles de previsiter et postvisiter dans la question
précédente ?
QUESTION 4 Comment obtenir en sortie la liste de tous les sommets dans l’ordre de leur première visite ?
Implémenter cela en CAML.
QUESTION 5 Remplacer la pile par une file pour obtenir un parcours en largeur et le vérifier sur des
exemples.
http://carnot.cpge.info 1
Lycée Carnot — 2016-2017 Option informatique MP/MP*
Algorithme 1 : explorer(G,s) : exploration en profondeur à partir d’un sommet.
Entrée : Graphe G= (S,A), sommet sS
1pile creer_pile_vide();
2empiler(s, pile);
3tant que pile est non vide faire
4tdepiler(pile);
5si t est marqué alors
6si t pas encore postvisité alors
7postvisiter(t);
8fin
9fin
10 sinon
11 prévisiter(t);
12 marquer t;
13 empiler(t, pile);
14 pour tout voisin u de t faire
15 si u n’est pas marqué alors
16 empiler(u, pile);
17 fin
18 fin
19 fin
20 fin
Algorithme 2 : parcours_pronfondeur(G) : parcours en profondeur d’un graphe.
Entrée : Graphe G= (S,A)
1pour s dans S faire
2si s n’est pas marqué alors
3explorer(G,s);
4fin
5fin
3 Temps de premier et dernier passage
Dans tout ce qui va suivre, on s’intéresse au parcours en profondeur, celui obtenu à l’aide d’une pile.
QUESTION 6 On considère une variable horloge initialisée à 0, qui est incrémentée à chaque fois que l’on
prévisite ou que l’on postvisite un sommet. On utilise également deux tableaux pre et post, dans lesquels
on met à jour pour chaque sommet son heure de prévisite (appelée aussi temps de premier passage) et
de postvisite (temps de dernier passage). Pour s,s0S, montrer que soit les intervalles [pre[s],post[s]] et
[pre[s0],post[s0]] sont disjoints, soit l’un est inclus dans l’autre. Que réprésente l’intervalle [pre[s],post[s]] ?
Implémenter cela en CAML et essayer sur quelques exemples.
4 Composantes connexes d’un graphe non-orienté
QUESTION 7 On veut modifier l’algorithme pour obtenir les composantes connexes, sous la forme d’un
tableau composantes composantes[s]est l’identifiant (un entier unique pour chaque composante)
de la composante connexe à laquelle appartient s. On va donc définir
let previsiter s composantes id =
composantes.(s) <- !id
;;
http://carnot.cpge.info 2
Lycée Carnot — 2016-2017 Option informatique MP/MP*
À quel endroit faut-il incrémenter la référence id pour que le parcours permette de calculer les compo-
santes connexes ?
QUESTION 8 Écrire une fonction is_connected :graph -> bool qui vérifie si un graphe est connexe.
QUESTION 9 Écrire une fonction connected_components :graph -> graph list qui renvoie les
sous-graphes correspondant aux composantes connexes.
5 Graphes orientés acycliques et tri topologique
Définition 1. Un ordre topologique d’un graphe orienté G = (S,A)est un ordre total 2sur les sommets tel que
si (s,s0)A alors s s0, c’est-à-dire compatible avec la relation d’ordre partielle donnée par les arcs.
QUESTION 10 Montrer qu’un graphe orienté qui admet un ordre topologique est acyclique.
QUESTION 11 Montrer que dans un graphe orienté acyclique G= (S,A), si (s,s0)Aalors post[s]>
post[s0].
QUESTION 12 En déduire un algorithme qui détecte si un graphe est acyclique et l’implémenter.
QUESTION 13 À l’aide des temps de dernier passage, trouver un algorithme qui, pour un graphe acyclique,
trie les sommets de ce graphe selon un ordre topologique et l’implémenter.
Remarque 1. Il y a donc équivalence, pour un graphe orienté, entre être acyclique et admettre un ordre topologique.
6 Composantes fortement connexes d’un graphe orienté
Soit G= (S,A)un graphe orienté.
QUESTION 14 Pourquoi ne peut-on pas simplement effectuer un parcours de graphe pour trouver les
composantes (fortement) connexes, comme dans le cas non-orienté ?
On définit le méta-graphe de Gcomme étant le graphe MG= (Cf,Af)Cfest l’ensemble des com-
posantes fortement connexes de Get Af={(c1,c2)C2
f,s1c1,s2c2,(s1,s2)A}.
QUESTION 15 Montrer que MGest un graphe orienté acyclique. À quelle condition a-t-on G=MG?
QUESTION 16 Soit cCftel que d+(c) = 0, on dit que cest un puits. Soit sc. Pourquoi la fonction
explorer au départ de sdans Gpermet de trouver exactement c? Ceci suggère un algorithme pour
trouver les composantes fortement connexes : (1) choisir un sommet sappartenant à un puits de MG;
(2) utiliser le parcours en profondeur à partir de sommet pour construire sa composante connexe ; (3)
supprimer cette composante du graphe initial ; (4) recommencer avec les sommets restants.
Le problème, c’est que l’on ne voit pas bien a priori comment trouver un sommet appartenant à un
puits de MG. En revanche, il est plus simple de trouver un sommet appartenant à une source de MG. Un
sommet cest une source si d(c) = 0.
QUESTION 17 Soient c1,c2Cf, montrer que si (c1,c2)Afalors
max
s1c1
post[s1]>max
s2c2
post[s2]
En déduire un algorithme permettant de trouver un sommet sappartenant à une source de Mf.
QUESTION 18 Pour trouver un puits de MG, on peut utiliser le graphe transposé de G(cf. EXERCICE 15 du
TP no2). Pourquoi les composantes fortement connexes de GRsont les mêmes que celles de G? Que vaut
Mf(GR)? En déduire un algorithme pour trouver un sommet sappartenant à un puits de Mf(G).
QUESTION 19 En déduire un algorithme pour trouver les composantes fortement connexes d’un graphe
oriente et l’implémenter en CAML. Montrer que sa complexité est toujours linéaire (i.e. O(|S|+|A|)).
http://carnot.cpge.info 3
1 / 3 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !