Algorithmes de graphes Olivier Baudon Université de Bordeaux 351, cours de la Libération, 33405 Talence Cedex, France 14 novembre 2016 Résumé Ces notes présentent les principaux algorithmes de graphes vus dans le cadre de l’UE Algorithmes de Graphes de la Licence Informatique de l’Université de Bordeaux Chapitre 1 Algorithmes 1.1 1.1.1 Parcours de graphes Parcours en largeur Algorithme 1 Parcours en largeur PL(G, s) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: couleur(s) ← GRIS d(s) ← 0 pere(s) ← N IL F ← {s} pour tout v ∈ V (G)\s faire couleur(v) ← BLAN C d(v) ← ∞ pere(v) ← N IL fin pour tant que F non vide faire v ← tete(F ) pour tout w ∈ Adj(v) faire si couleur(w) = BLAN C alors couleur(w) ← GRIS d(w) ← d(v) + 1 pere(w) ← v Enf iler(F, w) fin si fin pour Def iler(F ) couleur(v) ← N OIR fin tant que 2 Complexité 1.1.2 Parcours en profondeur Algorithme 2 Parcours en profondeur PP(G) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: pour tout v ∈ V (G) faire couleur(v) ← BLAN C pere(v) ← N IL fin pour temps ← 0 pour tout v ∈ V (G) faire si couleur(v) = BLAN C alors V isiterP P (v) fin si fin pour Algorithme 3 VisiterPP(v) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: d(v) ← temps ← temps + 1 couleur(v) ← GRIS pour tout w ∈ Adj(v) faire si couleur(w) = BLAN C alors pere(w) ← v V isiterP P (w) fin si fin pour couleur(v) ← N OIR f (v) ← temps ← temps + 1 1.1.3 Applications du parcours en profondeur Tri topologique Au cours d’un parcours en profondeur, à chaque fois que l’on noircit un sommet, il est inséré en tête de liste. A P P (G), rajouter une ligne 5 bis : liste ← {} A V isiterP P (v), rajouter trois lignes 3.1, 3.2, 3.3 si couleur(w) = GRIS alors retourner”Existence d’un circuit” 3 fin si une ligne 11 : IN SERER T ET E(liste, v) Composantes fortement connexes Algorithme 4 CFC(G) Exécuter PP(G) et trier les sommets selon un ordre décroissant de f 2: Calculer G−1 3: Exécuter PP(G−1 ) 4: Retourner les arborescences obtenues comme composantes fortement connexes de G 1: 1.2 1.2.1 Arbre de poids minimum Algorithme de Kruskal Algorithme 5 Kruskal(G, w) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: pour tout v de V (G) faire composante(v) ← {v} fin pour Trier E(G) dans un ordre croissant (e1 , . . . , em ) en fonction de w(e) i←1 E(T ) ← {} tant que |E(T )| < n − 1 faire si ei = (u, v) et composante(u) 6= composante(v) alors E(T ) ← E(T ) ∪ {ei } UNIFIER(composante(u), composante(v)) fin si i←i+1 fin tant que retourner E(T ) 1.2.2 Algorithme de Prim 4 Algorithme 6 Prim(G, w) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: F ← F ILE P RIORIT E(V (G), cle) pour tout v de V (G) faire cle(v) ← ∞ fin pour cle(r) ← 0 pere(r) ← N IL tant que F 6= ∅ faire u ← EXT RAIRE M IN (F ) pour tout v ∈ Adj(u) faire si v ∈ F et w(u, v) < cle(v) alors pere(v) ← u cle(v) ← w(u, v) fin si fin pour fin tant que 1.3 1.3.1 Plus court chemin Plus court chemin à partir d’un sommet Dijkstra G : graphe orienté w : E(G) → R+ s : source de G Bellman G : graphe orienté sans circuit w : E(G) → R s : source de G Algorithme de Ford G : graphe orienté w : E(G) → R s : source de G L’algorithme renvoie vrai si le graphe G est sans circuit négatif. 5 Algorithme 7 Dijkstra(G, w, s) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: pour tout v de V (G) faire d(v) ← ∞ pere(v) ← N IL couleur(v) ← BLAN C fin pour d(s) ← 0 F ← F ILE P RIORIT E({s}, d) tant que F 6= ∅ faire pivot ← EXT RAIRE M IN (F ) pour tout e = (pivot, v) arc sortant de pivot faire si couleur(v) = BLAN C alors si d(v) = ∞ alors INSERER(F, v) fin si si d[v] > d[pivot] + w(e) alors d[v] ← d[pivot] + w(e) pere[v] ← pivot fin si fin si fin pour couleur[pivot] ← N OIR fin tant que Algorithme 8 Bellman-court(G, w, s) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: TriTopologique(G) Soit v1 , . . . , vn l’ordre topologique calculé à l’étape 1 pour i de 1 à n faire d[vi ] ← ∞ pere[vi ] ← N IL fin pour d[s] ← 0 Soit j l’indice de s dans l’ordre topologique calculé à l’étape 1 pour i de j à n − 1 faire pour u ∈ Adj(vi ) faire si d[u] > d[vi ] + w(vi , u) alors d[u] ← d[vi ] + w[vi , u] pere[u] ← vi fin si fin pour fin pour 6 Algorithme 9 Bellman-long(G, w, s) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: pour tout v de V (G) faire d[v] ← ∞ pere[v] ← N IL npred[v) ← deg − [v] fin pour d[s] ← 0 INSERER FILE(F, s) tant que F non vide faire u ← T ET E F ILE(F ) DEFILER(F) pour v ∈ Adj(u) faire si d[v] > d[u] + w(u, v) alors d[v] ← d[u] + w[u, v] pere[v] ← u] fin si npred(v) ← nped[v] − 1 si npred(v) = 0 alors INSERER FILE(F, v) fin si fin pour fin tant que Algorithme 10 Ford(G, w, s) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: pour tout v de V (G) faire d[v] ← ∞ pere[v] ← N IL fin pour d[s] ← 0 pour i de 1 à n − 1 faire pour tout arc e = (u, v) ∈ E(G) faire si d[v] > d[u] + w(u, v) alors d[v] ← d[u] + w[u, v] pere[v] ← u] fin si fin pour fin pour pour tout arc e = (u, v) ∈ E(G) faire si d[v] > d[u] + w(u, v) alors retourner FAUX fin si fin pour retourner VRAI 7 1.3.2 Plus courts chemins entre toutes paires de sommets Algorithme de Floyd G est un graphe orienté, munis d’une fonction de poids sur les arcs w. Les sommets sont numérotés de 1 à n. Wi,j contiendra la plus courte distance entre le sommet i et le sommet j, P redi,j le sommet prédécesseur de j sur un plus court chemin de i à j. Algorithme 11 Floyd(G, w) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: pour i de 1 à n faire pour j de 1 à n faire si i = j alors W (i, j) ← 0 P red(i, j) ← i sinon si ij ∈ E(G) alors W (i, j) ← w(i, j) P red(i, j) ← i sinon W (i, j) ← ∞ P red(i, j) ← N IL fin si fin pour fin pour pour k de 1 à n faire pour i de 1 à n faire pour j de 1 à n faire si W (i, k) + W (k, j) < W (i, j) alors W (i, j) ← W (i, k) + W (k, j) P red(i, j) ← P red(k, j) fin si fin pour fin pour fin pour Algorithme de Warshall L’algorithme de Warshall est une adaptation de l’algorithme de Floyd au calcul de la fermeture transitive d’un graphe orienté. Wi,j vaudra 1 s’il existe un chemin de i à j dans le graphe G, 0 sinon. 8 Algorithme 12 Warshall(G, w) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: pour i de 1 à n faire pour j de 1 à n faire si i = j || ij ∈ E(G) alors W (i, j) ← 1 sinon W (i, j) ← 0 fin si fin pour fin pour pour k de 1 à n faire pour i de 1 à n faire pour j de 1 à n faire W (i, j) ← (W (i, k) & W (k, j)) k W (i, j) fin pour fin pour fin pour 1.4 1.4.1 Flots Algorithme de Ford et Fulkerson G : graphe orienté c : E(G) → R+ s : source de G t : puit de G On considère un arc (t, s) de capacité c(t, s) infinie. La valeur du flot sur cet arc sera la ”valeur du flot de s à t”. On note respectivement par I(e) et T (e) l’extrémité initiale et l’extrémité terminale d’un arc e. 9 Algorithme 13 FlotMax(G, c, s, t) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: pour tout e de E(G) faire f [e] ← 0 fin pour répéter Marquage(G, c, f, s, t) si t ∈ Y alors v←t C + ← {(t, s)} C− ← ∅ tant que v 6= s faire e ← A[v] si v = T [e] alors C + ← C + ∪ {e} v ← I[e] sinon C − ← C − ∪ {e} v ← T [e] fin si fin tant que fin si pour tout e ∈ C + faire f (e) ← f (e) + δ[t] fin pour pour tout e ∈ C − faire f (e) ← f (e) − δ[t] fin pour jusqu’à t 6∈ Y 10 Algorithme 14 Marquage(G, c, f, s, t) 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: Y ← {s} δ(s) ← +∞ M ax ← faux tant que t 6∈ Y etM ax =faux faire si il existe e = (u, v) avec u ∈ Y, v 6∈ Y, f (e) < c(e) alors Y ← Y ∪ {v} A[v] ← e δ[v] ← min(δ[u], c(e) − f (e)) sinon si il existe e = (u, v) avec v ∈ Y, u 6∈ Y, f (e) > 0 alors Y ← Y ∪ {u} A[u] ← e δ[u] ← min(δ[v], f (e)) sinon Max ← vrai fin si fin si fin tant que 11