Main
Main
Notes de cours
P UBLISHED BY CC
Licensed under the Creative Commons Attribution-NonCommercial 3.0 Unported License (the
“License”). You may not use this file except in compliance with the License. You may obtain a
copy of the License at [Link] Unless required
by applicable law or agreed to in writing, software distributed under the License is distributed on an
“AS IS ” BASIS , WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
I Union-Find
1 Graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.1 Définition 9
1.2 Représentations 9
1.2.1 Matrice d’adjacence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2.2 Liste d’adjacence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3 Chemins 10
1.4 Cycle 10
1.5 Connexe 10
1.6 Arbres 10
1.7 Arbre couvrants 10
1.8 Graphes valués 11
1.9 Algorithme de Kruskal (1956) 11
3 L’algorithme : Union-Find . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1 Définition 15
3.2 Exemple 15
3.3 Applications 15
3.4 Idée de l’algorithme 16
3.5 Retour sur Kruskal 16
3.6 Implémentation en Python 16
3.7 Complexité 17
3.8 UNION : Maîtriser la hauteur des arbres 17
3.9 FIND : Compresser les chemins 17
II Parcours d’arbres
6 Parcours de graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
6.1 Représentation des graphes (non orientés) 31
6.2 Parcours en largeur des graphes 31
6.3 Parcours en profondeur des graphes 33
6.3.1 Version récursive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
6.3.2 Version itérative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
IV Algorithmes de graphes
7 Algorithme de Kruskal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
7.1 Implémentation de l’algorithme de Krukal 37
7.2 Correction de l’algorithme de Kruskal 37
7.2.1 Lemme d’optimalité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
8 Algorithme de Prim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
8.1 Implémentation de l’algorithme de Prim (version optimisée) 39
8.2 Complexité de l’algorithme de Prim 40
10 Algorithme de Bellman-Ford . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
10.1 Idée 45
10.2 Implémentation en Python 46
10.3 Preuve 46
12 Cycles négatifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
12.1 Algorithme pour détecter les cycles négatifs 51
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
I
Union-Find
1 Graphes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.1 Définition
1.2 Représentations
1.3 Chemins
1.4 Cycle
1.5 Connexe
1.6 Arbres
1.7 Arbre couvrants
1.8 Graphes valués
1.9 Algorithme de Kruskal (1956)
3 L’algorithme : Union-Find . . . . . . . . . . . . . 15
3.1 Définition
3.2 Exemple
3.3 Applications
3.4 Idée de l’algorithme
3.5 Retour sur Kruskal
3.6 Implémentation en Python
3.7 Complexité
3.8 UNION : Maîtriser la hauteur des arbres
3.9 FIND : Compresser les chemins
1. Graphes
1.1 Définition
Définition 1.1.1 — Graphe. Un graphe est constitué d’un ensemble de sommets S d’un en-
semble d’arêtes A ⊆ S × S reliant les sommets. Les arêtes sont orientées (flèche) ou non orientées
(segment).
Les sommets peuvent représenter des villes, des stations de métro, des sites sur des cartes
géographiques, etc. Les arêtes peuvent symboliser des routes, des câbles, des liens, etc. Un graphe
peut ainsi représenter des cartes géographiques, le web, les réseaux sociaux, des modèles 3D
(animations), modèles physiques d’interactions...
1.2 Représentations
1 5
2 3 6
1 2 3 4 5 6
1 2 3
1 0 1 1 0 0 0
2 1 3 4
2 1 0 1 1 0 0
3 1 2 4
3 1 1 0 1 0 0
4 2 3
4 0 1 1 0 0 0
5 6
5 0 0 0 0 0 1
6 5
6 0 0 0 0 1 0
1.3 Chemins
Définition 1.3.1 — Chemin. Un chemin de longueur k de u à v dans un graphe G = (S, A) est
une suite de sommets u0 , u1 , ... uk telle que u0 = u, uk = v et on ne passe que par des arêtes de
G. ∀i ∈ J0, kK ∈ A
Définition 1.3.2 — Chemin simple. Un chemin simple est un chemin qui ne passe pas 2 fois
par le même sommet.
1.4 Cycle
Définition 1.4.1 — Cycles. Pour u ∈ S, un cycle est un chemin de longueur supérieure ou égale
à 3, de u à u, qui ne passe pas deux fois par le même sommet. Le graphe de la figure 1.3 possède
des cycles.
1.5 Connexe
Définition 1.5.1 — Connexe. Un graphe est connexe si ∀u, v ∈ S il existe un chemin de u à v
dans G. Le graphe de la figure 1.3 n’est pas connexe. Le graphe de la figure 1.6 est connexe.
1.6 Arbres
Définition 1.6.1 — Arbre. Un arbre est un graphe connexe sans cycle.
1 4
2
4 1
À ne pas confondre
Un problème décrit sur chaque donnée quel est le résultat attendu. ex : tri, recherche.
La structure de données décrit comment les données sont organisées et comment on y accède.
Un algorithme décrit le déroulement des étapes permettant de résoudre un problème.
Un programme (ou implémentation) est un choix des structures de données, des librairies,
du langage, de l’interface...
12 Chapitre 1. Graphes
Exercices
Exercice 1 : Ordres de grandeur
Donner les relations (o, O, θ ) entre les fonctions f et g suivantes :
1. f (n) = 2n et g(n) = 5n + 1 ;
2. f (n) = n2 et g(n) = n3 ;
3. f (n) = n2 et g(n) = 2n2 + 3n + 5 ;
4. f (n) = 8(log n)2 et g(n) = n − 2 ;
5. f (n) = log(n2 ) et g(n) = log n ;
6. f (n) = 2n et g(n) = n10 ;
7. f (n) = 2n+1 et g(n) = 2n ;
8. f (n) = 22n et g(n) = 2n .
2.1 Problèmes
Problème 2.1 Soit G = (S, A) et u, v ∈ S.
Répondre V RAI si il existe un chemin de u à v dans G, FAUX sinon.
Problème 2.2 Soit G = (S, A) et u, v ∈ S.
Est-ce qu’ajouter (u, v) à A crée un nouveau cycle ?
Proposition 2.1.1 Problème 2.1 ⇔ Problème 2.2
Si il existe un chemin de u à v : u = u1 , u2 , ...uk = v (qui ne passe pas 2 fois par le même
sommet) alors il existe un cycle si on ajoute u, v.
Dans l’autre sens, si ajouter (u, v) crée un nouveau cycle, alors il existe un chemin. En effet, si
le morceau cycle passe par u, v1 , ...vk , u alors G contient le chemin u, vk , ..., v1 , v.
Définition 2.1.1 Une composante connexe d’un graphe G = (S, A) est un sous-ensemble de
sommets S0 ⊆ S maximal tel que ∀u, v ∈ S0 , il existe un chemin de u à v dans G.
A
1 2
B 4 C
4 1
D
B C
B C
B C
3.1 Définition
On démarre avec des éléments d’un univers U (ici les sommets d’un graphe). On admet 2
opérations :
— UNION(u, v) : associe u et v (ici, on ajoute une arête)
— FIND(u, v) : permet de savoir si u et v sont associés, transitive (ici, si il existe un chemin de
u à v)
3.2 Exemple
3.3 Applications
— Segmentation d’image (combien de formes dans une image).
— Construction de labyrinthes.
— Kruskal, arbre couvrant minimal.
— Détection de cycles.
16 Chapitre 3. L’algorithme : Union-Find
w E
v D
u C
3.7 Complexité
— root1 : O(hauteur de l’arbre)
— find1 : 2 × hauteur + 1
— union1 : 4 × hauteur + 1
4.1 Complexité
Pour un algorithme A on note coûtA (x) le nombre d’opérations élémentaires que l’algorithme
effectue sur une entrée x.
Complexité au pire cas : coûtA (n) = max coûtA (x), x de largeur n.
n
Coût amorti d’un algorithme A : on exécute A(x1 ) A(x2 ) ... A(xn ) ; coût amorti = 1n ∑ coûtA (xi )
i=1
Complexité en moyenne : "définition mathématique formelle de, à la louche", on a une
µ
distinction sur les entrées µ, coûtA (x) = ∑ µ(x) coûtA (x).
x∼µ
En python :
1 class ArbreBinaire :
2 # par convention ArbreVide = None
3 def __init__ ( self , v , g = None , d = None ):
4 self . val = v
5 self . gauche = g
6 self . droite = d
Définition 4.2.2 — Arbre binaire de recherche. Un arbre binaire de recherche (ABR) est un
arbre étiqueté avec les propriétés suivantes :
1. [Link] est plus grand que toutes les valeurs de [Link].
2. [Link] est plus petit que toutes les valeurs de [Link].
22 Chapitre 4. Arbres binaires de recherche ABR
Définition4.2.3 — Taille d’un arbre. On écrit |A| la taille de l’arbre A son nombre de sommets.
0 si l’arbre est vide
|A| =
1 + |[Link]| + |[Link]| sinon
Définition 4.2.4 — Profondeur d’un nœud. On définit la profondeur d’un nœud v dans l’arbre
A comme la longueur du chemin de la racine de A jusqu’au sous arbre de racine v :
0 si [Link] = v
ProfA (v) = 1 + [Link] (v) si [Link] > v
1 + [Link] (v) si [Link] < v
Initialisation ("Base")
n = 1 : A a une seule valeur.
si v ∈ A alors v se trouve à la racine, 1 comparaison.
si v ∈
/ A alors on fera 5 comparaisons.
Si v ∈
/ A : Si [Link] = v, impossible
Si [Link] > v : ]comparaisons = T ([Link], v) + 3
≤ 5h([Link]) + 3 par hypothèse d’induction
≤ 5(h(A) − 1) + 3 par définition de h
≤ 5h(A)
Si [Link] < v : ]comparaisons = T ([Link], v) + 5
≤ 5h(A)
N
= ∑ t(i) + 12
i=2
N
2
≈ ∑ i + 21
i=1
N
1
≈ 2∑ i
i=1
CN
N+1 ≈ 2 ∗ N ln n
CN
On conclut que CN = 2(N + 1)N ln(N) et que le coût amorti N = 2(N + 1) ln(N)
III
Parcours de graphes
6 Parcours de graphes . . . . . . . . . . . . . . . . 31
6.1 Représentation des graphes (non orientés)
6.2 Parcours en largeur des graphes
6.3 Parcours en profondeur des graphes
5. Parcours d’arbres k-aire
Problème
Étant donné un arbre/graphe, on veut parcourir chaque sommet une et une seule fois.
On traite les arbres à arité (nombre d’enfants) variable. Chaque sommet A peut avoir un nombre
arbitraire de fils donnés dans une liste A. f ils.
28 Chapitre 5. Parcours d’arbres k-aire
1. Chaque sommet qui entre dans la file doit en sortir : l’algorithme ne se termine que lorsque
la file est vide.
5.4 Parcours en profondeur des arbres 29
2. Un sommet qui est entré dans la file ne peut pas y ré-entrer. En effet, il ne rentre que quand
son père sort. Mais par récurrence son père ne peut pas ré-entrer dans la file.
3. Chaque sommet de l’arbre entre dans la file. Sinon, son père n’est pas entré, ainsi de suite
tous ses ascendants ne sont pas rentrés jusqu’à la racine.
Conclusion : Le parcours en largeur parcourt les sommets une et une seule fois par ordre
croissant de profondeur. La complexité est 2|A| (en nombre de pop() et push(v)).
Exemple
3 6
1 5 7
Remarque : si on associe au parcours en profondeur "je vais visiter i" 7→ ( et "je quitte i" 7→ )
i i
on obtient une expression correctement parenthésée ; ici : ( ( ( ( ) ) ) ( ( ) ( ) ) )
43122136557764
Proposition 5.5.4 L’ensemble des sommets gris forment un chemin de la racine jusqu’à un sommet
de l’arbre.
Preuve de la proposition 5.5.4 Soient v1 , ... , vk les sommets gris à l’instant t. Supposons
v1 .debut < v2 .debut < ... < v1 . f in
On a montré : v1 .debut < v2 .debut < ... < v1 . f in
D’après la proposition 5.5.2, on a que vi+1 descendant de vi ∀i 1 ≤ i ≤ k. Mais il faut monter
que vi+1 est fils de vi . [...]
6. Parcours de graphes
1 def BFS ( S ):
2 t = 0 ; S . dist = 0; s . pred = None ; s . couleur = " gris "
3 Q = [ S ] # Queue
4 S . debut = t ; t += 1;
5 while not ( Q . vide ()):
6 noeud = Q . pop (0) # pop first
7 noeud . couleur = " noir "
8 noeud . fin = t ; t += 1
9 for v in noeud . voisins :
10 if v . couleur == " blanc " :
11 v . pred = noeud
12 v . dist = noeud . dist + 1
13 v . debut = t ; t += 1
14 v . couleur = " gris "
15 Q . push ( v ) # push last
Proposition 6.2.2 Tous les sommets accessibles à partir de s sont visités une et une seule fois.
Définition 6.2.2 — Graphe des prédécesseurs. Après le parcours (BFS ou DFS) à partir
de s ∈ S d’un graphe G = (S, A) , on appelle graphe des prédécesseurs : G pred = (S, A0 ) avec
A0 = {(u, [Link]), u ∈ S \ {S}}
Proposition 6.2.3 Si G est connexe, G pred est un arbre ; on l’appelle arbre de parcours.
Preuve de la proposition 6.2.3
G pred a n = |S| sommets et n − 1 arêtes ; G pred est connexe car on a parcouru tous les sommets
en passant par des arêtes du graphe.
Proposition 6.2.4 La complexité de BFS(S) en nombre de comparaisons est : ∑ ∑ 1 = 2|A| (car
x∈S v∈x
∑ représente la boucle while, 1 fois pour chaque sommet retiré de la file ; ∑ la boucle for)
x∈S v∈x
6.3 Parcours en profondeur des graphes 33
2 4 5
3 6 7
F IGURE 6.1 – G
Remarque : si on associe au parcours en profondeur "je vais visiter i" 7→ ( et "je quitte i" 7→ )
i i
on obtient une expression correctement parenthésée ; ici : ( ( ( ( ( ( ) ) ( ) ) ( ) )
12346776554321
Théorème 6.3.1 — Chemin blanc. Si u ⇒∗G pred v ⇔ au temps t = [Link] , un chemin blanc
relie u à v dans G.
34 Chapitre 6. Parcours de graphes
2 4 5
3 6 7
7 Algorithme de Kruskal . . . . . . . . . . . . . . . 37
7.1 Implémentation de l’algorithme de Krukal
7.2 Correction de l’algorithme de Kruskal
8 Algorithme de Prim . . . . . . . . . . . . . . . . . . 39
8.1 Implémentation de l’algorithme de Prim (version
optimisée)
8.2 Complexité de l’algorithme de Prim
10 Algorithme de Bellman-Ford . . . . . . . . . 45
10.1 Idée
10.2 Implémentation en Python
10.3 Preuve
12 Cycles négatifs . . . . . . . . . . . . . . . . . . . . . . 51
12.1 Algorithme pour détecter les cycles négatifs
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7. Algorithme de Kruskal
Définition 7.0.2 — Graphe valué. Un graphe G = (S, A) est valué (ou pondéré) si on y associe
une fonction de coût sur ses arêtes : w : A −→ R+ .
Définition 7.0.3 — Arbre couvrant minimal. Soit G = (S, A) et w une fonction de coût, trou-
ver A0 ⊆ A tel que T = (S, A0 ) soit un arbre couvrant de cout minimal coût(T ) = ∑ w(u, v)
(u, v)∈A0
1 from UF import UF
2 def Kruskal (G , w ):
3 T = []; cout = 0;
4 A = G . A # l ' ensemble des arretes de G
5 S = sorted ( A ) # A trie selon w croissant
6 for (u , v ) in S :
7 if not UF . find (u , v ): # si (u , v ) ne forme pas de cycle
8 T . append (( u , v ))
9 cout += w [( u , v )]
10 UF . union (u , v )
11 return (T , cout )
Définition 7.2.2 — Compatibilité. Pour toute solution partielle T 0 ⊆ G , on dit que T 0 est
compatible avec ACM(G, w) et on note T 0 v ACM(G, w) si ∃T ∈ ACM(G, w) tel que T 0 ⊆ T .
38 Chapitre 7. Algorithme de Kruskal
Preuve
On a G = (S, A) connexe, w ←− R+ S = S1 ∪ S2 S1 ∩ S2 = ∅
T 0 ⊆ T ∈ ACM(G, w)
T 0 ∩ S1 × S2 = ∅
Soit (u, v) de moindre coût parmi A ∩ S1 × S2
On veut montrer que T 0 ∪ (u, v) v ACM(G, w)
— cas 1 : si (u, v) ∈ T alors T 0 ∪ (u, v) ⊆ ACM(G, w)
— cas 2 : si (u, v) ∈/ T , comme G est connexe, T est un ACM.
T est connexe, (u0 , v0 ) ∈ S1 × S2 ∩ T car il existe un chemin de u à v dans T .
On a pris (u, v) de poids minimal ; donc w(u, v) ≤ (u0 , v0 ) .
∼
Regardons T = T \ {(u0 , v0 )} ∪ {(u, v)}
1. coût de T : coût dans S1 + coût dans S2 + w(u0 , v0 )
∼
coût de T : coût dans S1 + coût dans S2 + w((u, v)) or (u, v) ≤ w(u0 , v0 )
∼
Donc coût de T < coût de T∼
2. Si T est un arbre couvrant, T l’est aussi.
∼
Donc T ∈ ACM(G, w) et T 0 ∪ (u, v) ⊆ ACM(G, w)
Dans le cas de l’algorithme de Kruskal, supposons qu’à une itération donnée, on ait choisi les
arêtes T 0 et on a montré T v ACM(G, w) .
Posons S1 la composante connexe qui contient u et S2 = S \ S1 .
(u, v) que choisit Kruskal est celle de poids minimal parmi les arêtes qui restent qui ne forme pas
de cycle, comme u ∈ S1 , forcément v ∈ / S1 . Donc on peut l’ajouter d’après le lemme d’optimalité.
8. Algorithme de Prim
Exemple
A 1 B
Tas : (A, 0) (B, ∞) (C, ∞) (D, ∞) (E, ∞)
7 3 (A, 0) (B, ∞) (C, ∞) (D, ∞) (E, ∞)
(B, 1) (C, 7) (D, 18) (E, ∞)
18 C
(C, 3) (D, 18) (E, ∞)
2 (D, 3) (E, ∞)
(E, 10)
D 10 E
Communisme vs Capitalisme
A A
5 5 5 5
B 3 C B 3 C
F IGURE 9.1 – Arbre Couvrant minimal, coût = 8 F IGURE 9.2 – Plus courts chemins depuis A
Étant donné un graphe valué G, w et un sommet de départ s. On veut calculer les plus courts
chemins de s à v dans G ∀v ∈ S.
Définition 9.0.1 — Notations. Si C = (s = u0 , u1 , u2 , ... uk = v) est un chemin de s à v dans G,
on écrit :
C
— s −→G v
k
— w(C) = ∑ w(ui−1 , ui )
i=1
C
— δ (s, v) = min{w(C) : s −→G v}
C
Proposition 9.0.1 On peut toujours trouver des chemins Cu s −→ u tel que l’union des Cu forme
un arbre.
Preuve Supposons qu’on ait 2 sommets u, v des plus courts chemins Cu , Cv dont l’union forme
un cycle.
C1 C2
Les segments C1 , C2 x −→ y x −→ y ont le même coût, sinon supposons w(C1 ) < w(C2 ) alors
il y a un chemin plus court de s à v qui passe par C1 ; C2 n’est pas un plus court chemin, impossible.
À l’itération t, y ∈ T t , mais y a une priorité 6= ∞ donc y est dans le tas, tout comme u qui a
été choisi.
[Link] ≤ [Link] car u sort du tas
= δ (s, y) (II)
≤ δ (s, u) car y précède u sur un plus court chemin
≤ [Link] (P2)
⇒ toutes ces quantités sont égales ⇒ y = u
10. Algorithme de Bellman-Ford
Cet algorithme permet de trouver les plus courts chemins depuis un sommet source donné. Il est
cependant moins performant que Dijkstra, mais est distribuable, chaque sommet du réseau connaît
ses voisins, propage les résultats des calculs intermédiaires à ses voisins.
10.1 Idée
Commencer avec d(s) = 0 et d(u) = ∞ ∀u 6= s.
À chaque itération, on parcourt toutes les arêtes du graphe ; (u, v) ∈ A : si d(u) + w(u, v) < d(v)
On pose d(v) = d(u) + w(u, v) et pred(v) = u.
Exemple
B 4 D
2 1 2
A 8 E
12 1 4
C
2 2 2
B B D 6 B D 5
A A E A E
3 3
t =1 C t =2 C t =3 C
12 10 4
46 Chapitre 10. Algorithme de Bellman-Ford
On remarque qu’à l’itération t on trouve des plus courts chemins qui parcourent au plus t arêtes.
Un plus court chemin de s à u parcourt au plus n − 1 arêtes. Pour que l’algorithme soit correct,
il suffit de montrer qu’à l’itération t on a calculé les plus courts chemins passant par au plus t arêtes
et répéter n − 1 fois pour avoir tous les plus courts chemins de s aux autres sommets.
B 2 C
20 2
A 40 D
2 2
F 2 E
48 Chapitre 11. All pairs shortest paths
D Pred
A B C D E F A B C D E F
A 0 20 - - - 2 A A A - - - A
B 20 0 2 - - - B A B B - - -
t =1 C - 2 0 2 - 40 C - B C C - C
D - - 2 0 2 - D - - C D D -
E - - - 2 0 2 E - - - D E E
F 2 - 40 - 2 0 F A - C - E F
A B C D E F A B C D E F
A 0 20 22 - - 2 A A A B - - A
B 20 0 2 4 - 22 B A B B C - A
t =2 C 22 2 0 2 4 40 C B B C C D C
D - 4 2 0 2 4 D - C C D D E
E - - 4 2 0 2 E - - D D E E
F 2 22 40 4 2 0 F A A C E E F
etc.
Implémentation
Dans l’implémentation de l’algorithme il va falloir faire des copies, sinon à l’instant t, D contient
un mélange de δ t et δ t+1 .
1 from utils import dcopy
2 def PCC1 (G , w ):
3 inf = float ( " inf " )
4 D = { u :{ u : inf for u in G . sommets } for u in G . sommets }
5 Pred = { u :{ u : None for u in G . sommets } for u in G . sommets }
6 for u in G . sommets :
7 for v in G . sommets :
8 D [ u ][ v ] = w [ u ][ v ]
9 Pred [ u ][ v ] = None if w [ u ][ v ] == inf else u
10 D_next = dcopy ( D )
11 Pred_next = dcopy ( Pred )
12 for t in range (2 , len ( G . sommets )):
13 for u in G . sommets :
14 for v in G . sommets :
15 for x in v . voisins :
16 if D_next [ u ][ v ] > D [ u ][ x ] + w [ x ][ v ]:
17 D_next [ u ][ v ] = D [ u ][ x ] + w [ x ][ v ]
18 Pred_next [ u ][ v ] = x
19 D = dcopy ( D_next )
20 Pred = dcopy ( Pred_next )
21 return (D , Pred )
∀u , un plus court chemin de longueur au plus 2t+1 = 2 × 2t arêtes est composé de 2 plus courts
chemins de longueur au plus 2t .
≤ 2t ≤ 2t
u −−−−−−−−−→ x −−−−−−−−−→ v
Pour obtenir un plus court chemin de u à v en passant par au plus 2t+1 arêtes il suffit de prendre :
t t t
min{δ 2 (u, x), min{δ 2 (u, x) + δ 2 (x, v)}}
x∈S
t
On peut s’arrêter lorsque δ 2 ≥ n − 1 .
Implémentation
On note Pred[u][v] le prédécesseur de v dans le plus court chemin de u à v.
1 from utils import dcopy
2 from math import log , ceil
3 def PCC1 (G , w ):
4 inf = float ( " inf " )
5 D = { u :{ u : inf for u in G . sommets } for u in G . sommets }
6 Pred = { u :{ u : None for u in G . sommets } for u in G . sommets }
7 for u in G . sommets :
8 for v in G . sommets :
9 D [ u ][ v ] = w [ u ][ v ]
10 Pred [ u ][ v ] = None if w [ u ][ v ] == inf else u
11 D_next = dcopy ( D )
12 Pred_next = dcopy ( Pred )
13 for t in range (2 , ceil ( log ( len ( G . sommets ) - 1 , 2))):
14 for u in G . sommets :
15 for v in G . sommets :
16 for x in G . sommets :
17 if D_next [ u ][ v ] > D [ u ][ x ] + w [ x ][ v ]:
18 D_next [ u ][ v ] = D [ u ][ x ] + w [ x ][ v ]
19 Pred_next [ u ][ v ] = Pred [ x ][ v ]
20 D = dcopy ( D_next )
21 Pred = dcopy ( Pred_next )
22 return (D , Pred )
δ 1, ... , k (u, v) = min{δ 1, ..., k (u, v), δ 1, ... , k (u, k + 1)δ 1, ... , k (k + 1, v)}
50 Chapitre 11. All pairs shortest paths
A B C D E F A B C D E F
A 0 20 - - - 2 A - - - - - -
B 20 0 2 - - - B - - - - - -
C - 2 0 2 - 40 C - - - - - -
D 40 - 2 0 2 - D - - - - - -
E - - - 2 0 2 E - - - - - -
F 2 - - - 2 0 F - - - - - -
Implémentation
1 from utils import dcopy
2 def Floyd_Warshall (G , w ):
3 inf = float ( " inf " )
4 D = { u :{ u : inf for u in G . sommets } for u in G . sommets }
5 Pred = { u :{ u : None for u in G . sommets } for u in G . sommets }
6 for u in G . sommets :
7 for v in G . sommets :
8 D [ u ][ v ] = w [ u ][ v ]
9 Pred [ u ][ v ] = None if w [ u ][ v ] == inf else u
10 D_next = dcopy ( D )
11 Pred_next = dcopy ( Pred )
12 for x in G . sommets :
13 for u in G . sommets :
14 for v in G . sommets :
15 if D [ u ][ x ] + D [ x ][ v ] < D_next [ u ][ v ]:
16 D_next [ u ][ v ] = D [ u ][ x ] + D [ x ][ v ]
17 Pred_next [ u ][ v ] = Pred [ x ][ v ]
18 D = dcopy ( D_next )
19 Pred = dcopy ( Pred_next )
20 return (D , Pred )
12. Cycles négatifs
k−1
Définition 12.0.1 — Cycle négatif. Un cycle C = {u1 , ... , uk est négatif si ∑ w(ui , ui + 1) +
i=1
w(uk , u1 < 0. Pour simplifier les équations, on écrit WC = ∑ w(u, v)
(u, v)∈C
Remarque : l’algorithme de Dijkstra ne marche pas pour les graphes avec des poids négatifs.
Composante connexe . . . . . . . . . . . . . . . . . . . . 13
Connexe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
A Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Cycle négatif . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
ACM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Algorithme de Kruskal . . . . . . . . . . . . . . . . . . . 37
Algorithme de Prim . . . . . . . . . . . . . . . . . . . . . 39
Arbre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 D
Arbre binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Dijkstra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Arbre binaire de recherche . . . . . . . . . . . . . . . 21
Arbre couvrant . . . . . . . . . . . . . . . . . . . . . . 10, 11
Arbre couvrant minimal . . . . . . . . . . . . . . . . . . 37
Arbre de parcours . . . . . . . . . . . . . . . . . . . . . . . 32 F
FIND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
B Floyd-Warshall (Algorithme) . . . . . . . . . . . . . 49
Bellman-Ford (algorithme) . . . . . . . . . . . . . . . 45
G
C Graphe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Graphe des prédécesseurs . . . . . . . . . . . . . . . . 32
Chemin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Graphe pondéré . . . . . . . . . . . . . . . . . . . . . 11, 37
Chemin simple . . . . . . . . . . . . . . . . . . . . . . . . . 10
Chemins . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31, 33 Graphe valué . . . . . . . . . . . . . . . . . . . . . . . . 11, 37
Coût amorti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Compatibilité . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Complexité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 H
Complexité au pire cas . . . . . . . . . . . . . . . . . . . 21
Complexité en moyenne . . . . . . . . . . . . . . . . . 21 Hauteur (Arbre) . . . . . . . . . . . . . . . . . . . . . . . . . 22
54 INDEX
Insertion (ABR) . . . . . . . . . . . . . . . . . . . . . . . . 23
Kruskal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Liste d’adjacence . . . . . . . . . . . . . . . . . . . . . . . 10
Matrice d’adjacence . . . . . . . . . . . . . . . . . . . . . 10
Structure de données . . . . . . . . . . . . . . . . . . . . 11
UNION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15