Vous êtes sur la page 1sur 12

CPGE-AGADIR MP-PSI

Introduction à la théorie des graphes

1) Origines

La date de naissance de la théorie des graphes peut être fixée à


l'année 1735.
L'histoire raconte que les habitants de Königsberg
(maintenant Kaliningrad en Russie) souhaitaient savoir s'il
existait un moyen de partir de chez soi, emprunter tous les
7 ponts, une fois et une seule, et revenir dans sa demeure.
Leonhard Euler, montra que c'était impossible et fut amené
pour cela à introduire les premiers rudiments de théorie des
graphes, dont celle de cycle eulérien qui va être définie ci-
dessous.
2) Définitions

 Graphe :

Un graphe G est défini par G=(S,A), où S est un ensemble de sommets et A l’ensemble d'arcs (ou arêtes) ; Un arc
(ou arête) est un couple de sommets, donc, un élément du produit cartésien SxS

Exemple

S={1, 2, 3, 4}
A={ {1, 2} , {1,3} , {1,4} , {2,4} , {3,4} }

 Graphe orienté et Graphe non orienté :

Si les arêtes ne sont pas orientées, on parle d’un graphe non orienté. Dans le cas contraire on parle d’un graphe
orienté et les arêtes sont appelées aussi les arcs.

Exemple
Graphe non orienté Graphe orienté

S={1, 2, 3, 4} S={1, 2, 3, 4}
A={ {1, 2} , {1,3} , {1,4} , {2,4} , {3,4} } A={(1, 2) , (1,3), (1,4) , (2,4) ,(3,4)}

Introduction aux Graphes 1 /12 M.GUEROIHI


 Graphe Pondéré :

Un graphe pondéré est défini par le triplet (S, A, C) où : S est l’ensemble des sommets, A est l’ensemble des
arrêtes (ou arcs), et C est la fonction de coût de A dans IR. Par convention Ca représente le coût ou le poids de
l’arc (ou de l’arête) a (distance entre 2 villes, temps du trajet…).

3) Terminologies

 Ordre du Graphe : le nombre de sommet du Graphe


 Degré d’un sommet : nombre d’arêtes reliées à ce sommet
 Degré d’un graphe : le degré maximum des sommets
 Adjacences: Deux arcs sont dits adjacents s'ils ont une extrémité en commun. Et deux sommets sont dits
adjacents si un arc les relie.
Exemple :
Le graphe ci-contre est d'ordre 4.
Les sommets A et C sont adjacents car ils sont reliés par une arête.
Le sommet C est de degré 3 car 3 arêtes partent de C.

 Boucle : est un arc qui part d’un sommet vers le même sommet

 Chaîne : Une chaine de longueur n est une suite de n arêtes qui relient un sommet i à un autre j ou à lui-
même.
 Cycle : Un cycle est une chaine qui permet de partir d’un sommet et revenir à ce sommet en parcourant
une et une seule fois les autres sommets.
Exemple :
Dans le graphe ci-contre,
A – B – C – D – E est une chaîne de longueur 4.
B – C – D – E – B est un cycle de longueur 4.

 Distance entre deux sommets i et j est la longueur de la


chaine la plus courte qui les relie

 Chemin : c’est une chaine bien orientée


 Circuit : est un cycle "bien orienté", à la fois cycle et chemin.

Introduction aux Graphes 2 /12 M.GUEROIHI


 Chaine eulérienne: une chaine est dite eulérienne est une chaine comportant exactement une fois toutes
les arêtes du graphe.
Exemple :
Une chaîne eulérienne peut être tracée d'un trait continu sans repasser par une
arête déjà tracée.
C'est le cas du célèbre jeu de l'enveloppe où l'on doit tracer sans lever le stylo ni
repasser sur un trait déjà tracé :
La chaîne B – A – D – B – C – D – E – A – C est par exemple une chaine eulérienne.

 Chaine hamiltonienne : est une chaine qui passe par tous les sommets une et
une seule fois.

La chaîne d– e – c – b – a est par exemple une chaine hamiltonienne.

 Cycle eulérien : si le sommet de départ d’une chaine eulérienne est celui d’arrivé on parle de cycle
eulérienne
 Cycle hamiltonien : c’est un cycle passant une seule fois par tous les sommets d’un graphe et revenant au
sommet de départ.

Chaine eulérienne : e– b– d– e– c– a– b– c– d
Chaine hamiltonienne : d – e– c – b– a
Pas de cycle eulérien
Cycle hamilotnien : d – e – b – a – c – d

Introduction aux Graphes 3 /12 M.GUEROIHI


Dans le graphe suivant, la chaîne A – B – C – D – E – F – A est un cycle eulérien et hamiltonien.

 Graphe eulérien : Un graphe admettant un cycle eulérien est dit Graphe eulérien
 Graphe hamiltonien: Un graphe admettant un cycle hamiltonien est dit Graphe hamiltonien
 Graphe Connexe : Un graphe connexe est un graphe dont tout couple de sommets peut être relie par une
chaine de longueur n>=1.
Graphe Connexe Graphe non connexe

 Un graphe est dit complet si deux sommets quelconques sont adjacents.


Exemple :
Le réseau d'ordinateur représenté ci-contre est un graphe complet en effet
tous les sommets sont reliés deux à deux.

4) Théorèmes d’Euler

Théorème 1:
Un graphe connexe G admet un cycle eulérien si et seulement si tous ses sommets sont de degré pair.
Théorème 2:
Un graphe connexe G admet une chaîne eulérienne distincte d'un cycle si et seulement si le nombre de sommets
de G de degré impair est égal à 2.
Dans ce cas, si A et B sont les deux sommets de G de degré impair, alors le graphe G admet une chaîne eulérienne
d'extrémités A et B.
Exemple :
Dans le graphe ci-contre, tous les sommets sont de degré pair sauf B et C.
Ce graphe admet donc bien une chaîne eulérienne.

Alors le graphe admet une chaîne eulérienne d'extrémités B et C :


La chaîne B – A – D – B – C – D – E – A – C

Introduction aux Graphes 4 /12 M.GUEROIHI


Exercice 1:
Vérifier si les graphes suivant sont eulériens ou admettent des chaines eulériens.

5) Représentation d’un Graphe

Un graphe peut être implémenté de différentes manières selon le langage utilisé. En Python en peut représenter
un graphe à l’aide d’un dictionnaire ou à l’aide d’une matrice d’adjacence.
Exemple :
G={ G=[
1 : [2,5] , [0, 1, 0, 0, 1, 0],
2 : [1,3,5] , [1, 0, 1, 0, 1, 0],
3 : [2,4] , [0, 1, 0, 1, 0, 0],
4 : [3,5,6] , [0, 0, 1, 0, 1, 1],
5 : [1,2,4] , [1, 1, 0, 1, 0, 0],
6 : [4] [0, 0, 0, 1, 0, 0]
} ]

Graphe Dictionnaire Matrice d’adjacence

Propriétés de la matrice d’adjacence


 La matrice est symétrique si le graphe n’est pas orienté.
 La somme des nombres d’une même ligne (ou d’une même colonne) donne le degré du sommet
correspondant.
 La diagonale ne contient que des zéros.
 Les termes gij de la matrice Gn donnent le nombre de chaînes de longueur n reliant i à j

Introduction aux Graphes 5 /12 M.GUEROIHI


Exercice 2:
Construire la matrice d’adjacence du premier graphe de l'exercice1.

Exercice 3:
Soit un graphe non orienté et non pondéré de matrice d’adjacence G.
Ecrire les fonctions suivantes :
1- degre(G,i) : qui retourne le degré d’un sommet ayant l’indice i
2- nombreArcs(G) qui retourne le nombre d’arcs.
3- cycleEulerien(G) : qui retourne True si le graphe admet un cycle eulérien, False sinon.
4- chaineEulerienne(G): qui retourne True si le graphe admet une chaine eulérienne, False
sinon
5- chaineEulerienne2(G) : qui retourne une liste ayant les indices des extrémités de la chaine
eulérienne si elle existe. None sinon

Introduction aux Graphes 6 /12 M.GUEROIHI


6) Parcours d’un graphe
Par la suite nous utilisons la représentation en utilisant la matrice d’adjacence d’un graphe.
a- Le parcours en profondeur d'abord DFS (Depht First Search) : on va aussi loin que possible en faisant des
choix lors des branchements, et ensuite on remonte aussi près que possible pour faire les choix restants ;
Algorithme :
 Initialement tous les nœuds sont marqués " non visités".
 Choisir un nœud v de départ et le marquer " visité".
 Chaque nœud adjacent à v, non visité, est à son tour visité en utilisant DFS récursivement.
 Une fois tous les nœuds accessibles à partir de v ont été visités, la recherche de v( DFS(v) ) est complète.
 Si certains nœuds du graphe restent "non visités", sélectionner un comme nouveau nœud de départ et
répéter le processus jusqu'à ce que tous les nœuds soient visités.
Exemple : Soit le graphe suivant :

C
I
B F Le parcours en profondeur de ce graphe :
A
A, B, C, F, D, H, I, G, E
D
H
E
G

Implémentation du parcours en profondeur en Python.


def parcoursProfondeur(G) : def succNonvisite(G,i,T) :
T=[0]*len(G) n=len(G[i])
L=[] #liste à retourner L=[ ]
for i in range (len(G)) : for j in range(n) :
if T[i]==0 : If G[i][j]==1 and T[j]==0 :
L += parcoursDFS(G,i,T) L.append(j)
return L return L

def parcoursDFS(G,i,T) :
P=[i] #initialiser une pile P
C=[] #liste à retourner
while P!=[] :
n=P.pop()
if T[n]==0 :
C+=[n]
T[n]=1 #marquer le noeud comme visité
succ= succNonvisite(G, n,T)
succ.reverse()
for x in succ : P.append(x)
return C
La fonction parcoursDFS peur être récursive :
def DFSRecursif(G,i,T) :
T[i]= 1 #marquer le noeud comme visité
succ=succNonvisite(G, i ,T)
for x in succ:
if T[x]==0: return [i]+ DFSRecursif(G,x,T)
return [i]
parcoursProfondeur(G) : fonction qui lance le parcours, elle faire appel à la fonction parcoursDFS.
succNonVisite(G,i,T) : retourne la liste des successeurs de sommet d’indice i non visités.

Introduction aux Graphes 7 /12 M.GUEROIHI


b- Le parcours en largeur d'abord (Breadh First Search ): on procède par niveau en considérant d'abord tous les
sommets à une distance donnée, avant de traiter ceux du niveau suivant.
Exemple :

C
I
B F Le parcours en largeur de ce graphe :
A
A, B, D, E, C, G, F, H, I
D
H
E
G

En python :

def ParcoursEnlargeur(G) :
def BFS(G,i,T) :
T=[0]*len(G) #marquer non visités F=[i] #initialiser la file
C=[] #liste à retourner
L=[] #liste à retourner
while F !=[ ] :
for i in range(len(G)) : n=F.pop(0) #défiler
if T[n]==0 :
if T[i]==0:
T[n]=1
L+=BFS(G,i,T) C+=[n]
succ= succNonvisite(G,n,T)
return L
F+= succ
return C

7) Le Plus court chemin

Il existe de nombreux algorithmes déterminant un ou le plus court chemin dans un graphe connexe pondéré.
Par exemple: Warshall, Floyd, Dijkstra, Branch and Bound, Bellman-Ford, A star
On se limitera à la recherche d'un plus court chemin entre deux sommets du graphe pondéré avec des poids
positifs en utilisant la matrice d’adjacence pour représenter le graphe.
 Algorithme de dijkstra
E. W. Dijkstra (1930-2002) a proposé en 1959 un algorithme qui permet de déterminer le plus court chemin entre
deux sommets d'un graphe connexe pondéré (orienté ou non) dont le poids lié aux arêtes est positif ou nul.

Exemple
2
Le graphe ci-contre représente le réseau A D
routier d'une région qui prend en compte
7
le sens de la circulation, chaque arc 5 2
1 4
représente une route à sens unique dont
le poids est la distance en kilomètre 3 1
entre deux sommets. Quel est l'itinéraire E B G S
le plus court qui relie E à S ? 4
2
1 3 6
Principe de l'algorithme de Dijkstra
2
L'algorithme dû à Dijkstra est basé sur le C F
principe suivant :
Si le plus court chemin reliant E à S passe par les sommets s1 , s2 , …, sk alors, les différentes étapes sont aussi les
plus courts chemins reliant E aux différents sommets s1 , s2 , …, sk.

Introduction aux Graphes 8 /12 M.GUEROIHI


On construit de proche en proche le chemin cherché en choisissant à chaque itération de l'algorithme, un sommet
si du graphe parmi ceux qui n'ont pas encore été traités, tel que la longueur connue provisoirement du plus court
chemin allant de E à si soit la plus courte possible.

Initialisation de l'algorithme :

Étape 1 : On affecte le poids 0 au sommet origine (E) et on attribue provisoirement un poids ∞ aux autres
sommets.

Répéter les opérations suivantes tant que le sommet de sortie (S) n'est pas affecté d'un poids définitif.

Étape 2 : Parmi les sommets dont le poids n'est pas définitivement fixé choisir le sommet X de poids p minimal.
Marquer définitivement ce sommet X affecté du poids p(X).

Étape 3 : Pour tous les sommets Y qui ne sont pas définitivement marqués, adjacents au dernier sommet fixé X :

 Calculer la somme s du poids de X et du poids de l'arête reliant X à Y.


 Si la somme s est inférieure au poids provisoirement affecté au sommet Y, affecter provisoirement à Y le
nouveau poids s et indiquer entre parenthèses le sommet X pour se souvenir de sa provenance.

Quand le sommet S est définitivement marqué

Le plus court chemin de E à S s'obtient en écrivant de gauche à droite le parcours en partant de la fin S.

Pour faciliter la recherche du plus court chemin il est commode de présenter les résultats dans un tableau :

E A B C D F G S Sommet sélectionné et commentaires


0 ∞ ∞ ∞ ∞ ∞ ∞ ∞ E de poids 0 on marque les sommets adjacents A, B et C

2(E C on sélectionne les sommets adjacents G et F, on les


5(E) 3(E) ∞ ∞ ∞ ∞
) marque provisoirement G(2+3) et F(2+2)

B le sommet adjacent A est affecté d'un poids égal à 4


5(B) 3(E) ∞ 4(C) 5(C) ∞
(3+1<5)

A le sommet D va être marqué provisoirement avec un


4(B) ∞ 4(C) 5(C) ∞
poids 6= 4+2

F le sommet adjacent D sera affecté d'un poids égal à 5


6(A) 4(C) 5(C) ∞ (4+1<6) le sommet S va être marqué provisoirement
avec un poids 10= 4+6

5(F) 5 (C) 10 (F) D on conservera le poids de S (5+7>10)

5 (C) 10 (F) G le sommet adjacent est déjà traité

10 (F) S

Pour déterminer le trajet le plus court on remonte les sommets en partant de S :

S vient de F qui vient de C qui vient de E.

Le plus court chemin est E-C-F-S, la distance parcourue est de 10 km.

Introduction aux Graphes 9 /12 M.GUEROIHI


Exercice :

Déterminer le chemin le plus court entre I et J dans le graphe suivant :

9 D 7
A E
6
5 4
2 2
3

8 2 9 J
I G H

3 1 5
6 3 4

7 8
B C F

Présenter les résultats dans un tableau.

I A B C D E F G H J Sommet sélectionné
0 ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞ ∞

Introduction aux Graphes 10 /12 M.GUEROIHI


def dijkstra(G,s) : #G : Matrice d'adjacence s:indice du sommet de départ
infini =G[0][0] #infini est la valeur des cases non définies
n=len(G) # le nombre de sommets
D=[infini for i in range (n)] # initialisation des couts du plus court chemin entre
D[s]=0 i et s.
P=[s for i in range(n)] # P[i] : dernier sommet visité avant i.
C=[i for i in range(n)] # Sommets à visiter
while C !=[] : # tant qu’il y a des sommets à visiter
x=minD(D,C) # le prochain sommet le plus proche
for k in C :
if D[x]+G[x][k]< D[k]: #si la distance vers k est minimale en passant par x
D[k]=D[x]+G[x][k] #Mise à jour de la distance de k
P[k]=x #mise à jour du sommet visité k
C.remove(x) #ne plus revenir
return P,D

Sachant que la fonction minD(D,C)retourne l’indice du sommet de C ayant la petite valeur dans D. c.à.d. le
sommet prochain ayant une distance minimale avec le sommet du départ.
def minD(D,C) :
imin = C[0]
for i in C :
if D[i] < D[imin] : imin = i
return imin

Exemple d’exécution :
35 D Gr=[ [99, 3, 12, 99, 99, 99, 99],
A [99, 99, 99, 5, 35, 99, 99],
13
3 8 [99, 99, 99, 9, 99, 15, 99],
5
[99, 99, 99, 99, 8, 10, 99],
E C S
10 [99, 99, 99, 99, 99, 99, 13],
12 9 14 [99, 99, 99, 99, 99, 99, 14],
B 15 [99, 99, 99, 99, 99, 99, 99]
F
]
>>>dijkstra(Gr,0)
([0, 0, 0, 1, 3, 3, 4] , [0, 3, 12, 8, 16, 18, 29]) # La chaîne la plus courte de poids 29 se lit à l’envers en partant du sommet 6

Fonction permettant de déduire le chemin le plus court:


def cheminPlusCourt(sommets,G,s):
"""
retourne la liste des sommets constituant le chemin le plus cours
d'un grahpe de matrice d'Adjacence G,
de la liste des sommets sommets, dont s est l'indice du sommet de départ.
"""
P,D=dijkstra(G,s)
i=-1 #remonter le chemin depuis le sommet d’arrivée
L=[sommets[-1]]
while P[i]!=s:
L=[sommets[P[i]]]+L
i=P[i]
L=[sommets[s]]+L
return(L,D[-1])

Introduction aux Graphes 11 /12 M.GUEROIHI


#programme principal Execution:

Gr=[[99, 3, 12, 99, 99, 99, 99], chemin plus court : ['E', 'A', 'C', 'D', 'S']
[99, 99, 99, 5, 35, 99, 99],
cout = 29
[99, 99, 99, 9, 99, 15, 99],
[99, 99, 99, 99, 8, 10, 99],
[99, 99, 99, 99, 99, 99, 13],
[99, 99, 99, 99, 99, 99, 14],
[99, 99, 99, 99, 99, 99, 99]
]
sommets=['E', 'A','B','C', 'D','S']
chemin, cout = cheminPlusCourt(sommets, Gr, 0)

print("chemin plus court : " , chemin)


print ( " cout =",cout)

Introduction aux Graphes 12 /12 M.GUEROIHI

Vous aimerez peut-être aussi