* Une arête d'un graphe **orienté** est représentée par une paire **ordonnée** $(u,v)\neq(v,u)$, avec $u,v\in V$.
* Les arêtes sont orientées dans un graphe orienté (étonnant non?).
## Exemple
::: columns
:::: column

::::
:::: column
## Que valent $V$, $|V|$, $E$, et $|E|$?
. . .
\begin{align*}
V&=\{1, 2, 3, 4\},\\
|V|&=4,\\
E&=\{(1,2),(2,3),(2,4),(4,1),(4,2)\},\\
|E|&=5.
\end{align*}
::::
:::
# Généralités
## Définition
* Le somme $v$ est **adjacent** au sommet $u$, si et seulement si $(u,v)\in E$;
* Si un graphe non-orienté contient une arête $(u,v)$, $v$ est adjacent à $u$ et $u$ et adjacent à $v$.
## Exemple
::: columns
:::: column
{width=80%}
::::
:::: column
{width=80%}
::::
:::
# Généralités
## Définition
* Un **graphe pondéré** ou **valué** est un graphe dont chaque arête a un
poids associé, habituellement donné par une fonction de pondération $w:E\rightarrow\mathbb{R}$.
## Exemples
{width=80%}
# Généralités
## Définition
* Dans un graphe $G(V,E)$, une **chaîne** reliant un sommet $u$ à un sommet $v$ est une suite d'arêtes entre les sommets, $w_0$, $w_1$, ..., $w_k$, telles que
* Un **cycle** dans un graphe *non-orienté* est une chaîne de longueur $\geq 3$ telle que le 1er sommet de la chaîne est le même que le dernier, et dont les arêtes sont distinctes.
* Pour un graphe *orienté* on parle de **circuit**.
* Un graphe sans cycles est dit **acyclique**.
## Exemples
{width=100%}
# Question de la mort
* Qu'est-ce qu'un graphe connexe acyclique?
. . .
* Un arbre!
# Représentations
* La complexité des algorithmes sur les graphes s'expriment en fonction du nombre de sommets $V$, et du nombre d'arêtes $E$:
* Si $|E|\sim |V|^2$, on dit que le graphe est **dense**.
* Si $|E|\sim |V|$, on dit que le graphe est **peu dense**.
* Selon qu'on considère des graphes denses ou peu denses, différentes structure de données peuvent être envisagées.
## Question
* Comment peut-on représenter un graphe informatiquement? Des idées (réflexion de quelques minutes)?
. . .
* Matrice/liste d'adjacence.
# Matrice d'adjacence
* Soit le graphe $G(V,E)$, avec $V=\{1, 2, 3, ..., n\}$;
* On peut représenter un graphe par une **matrice d'adjacence**, $A$, de dimension $n\times n$ définie par
$$
A_{ij}=\left\{\begin{array}{ll}
1 & \mbox{si } i,j\in E,\\
0 & \mbox{sinon}.
\end{array} \right.
$$
::: columns
:::: column
## Exemple
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
1---2;
1---4;
2---5;
4---5;
5---3;
```
::::
:::: column
\footnotesize
## Quelle matrice d'adjacence?
. . .
```
|| 1 | 2 | 3 | 4 | 5
===||===|===|===|===|===
1 || 0 | 1 | 0 | 1 | 0
---||---|---|---|---|---
2 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
3 || 0 | 0 | 0 | 0 | 1
---||---|---|---|---|---
4 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
5 || 0 | 1 | 1 | 1 | 0
```
::::
:::
# Matrice d'adjacence
## Remarques
* Zéro sur la diagonale.
* La matrice d'un graphe non-orienté est symétrique
$$
A_{ij}=A_{ji}, \forall i,j\in[1,n]
$$.
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
1---2;
1---4;
2---5;
4---5;
5---3;
```
::::
:::: column
\footnotesize
```
|| 1 | 2 | 3 | 4 | 5
===||===|===|===|===|===
1 || 0 | 1 | 0 | 1 | 0
---||---|---|---|---|---
2 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
3 || 0 | 0 | 0 | 0 | 1
---||---|---|---|---|---
4 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
5 || 0 | 1 | 1 | 1 | 0
```
::::
:::
# Matrice d'adjacence
* Pour un graphe orienté (digraphe)
::: columns
:::: column
## Exemple
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
2-->1;
1-->4;
2-->5;
5-->2;
4-->5;
5-->3;
```
::::
:::: column
\footnotesize
## Quelle matrice d'adjacence?
. . .
```
|| 1 | 2 | 3 | 4 | 5
===||===|===|===|===|===
1 || 0 | 0 | 0 | 1 | 0
---||---|---|---|---|---
2 || 1 | 0 | 0 | 0 | 1
---||---|---|---|---|---
3 || 0 | 0 | 0 | 0 | 0
---||---|---|---|---|---
4 || 0 | 0 | 0 | 0 | 1
---||---|---|---|---|---
5 || 0 | 1 | 1 | 0 | 0
```
::::
:::
* La matrice d'adjacence n'est plus forcément symétrique
$$
A_{ij}\neq A_{ji}.
$$
# Stockage
* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe orienté?
. . .
* $\mathcal{O}(|V|^2)$.
* Quel est l'espace nécessaire pour stocker une matrice d'adjacence pour un graphe non-orienté?
. . .
* $\mathcal{O}(|V|-1)|V|/2$.
# Considérations d'efficacité
* Dans quel type de graphes la matrice d'adjacence est utile?
. . .
* Dans les graphes denses.
* Pourquoi?
. . .
* Dans les graphes peu denses, la matrice d'adjacence est essentiellement composée de `0`.
## Remarque
* Dans la majorité des cas, les grands graphes sont peu denses.
* Comment représenter un graphe autrement?
# La liste d'adjacence (non-orienté)
* Pour chaque sommet $v\in V$, stocker les sommets adjacents à $v$-
* Quelle structure de données pour la liste d'adjacence?
. . .
* Tableau de liste chaînée, vecteur (tableau dynamique), etc.

::::
:::: column
. . .

::::
:::
# Algorithme de Dijkstra
## Idée générale
* On assigne à chaque noeud une distance $0$ pour $s$, $\infty$ pour les autres.
* Tous les noeuds sont marqués non-visités.
* Depuis du noeud courant, on suit chaque arête du noeud vers un sommet non visité et on calcule le poids du chemin à chaque voisin et on met à jour sa distance si elle est plus petite que la distance du noeud.
* Quand tous les voisins du noeud courant ont été visités, le noeud est mis à visité (il ne sera plus jamais visité).
* Continuer avec le noeud à la distance la plus faible.
* L'algorithme est terminé losrque le noeud de destination est marqué comme visité, ou qu'on a plus de noeuds qu'on peut visiter et que leur distance est infinie.
# Algorithme de Dijkstra
## Pseudo-code (5min, matrix)
\footnotesize
. . .
```C
tab dijkstra(graph, s, t)
pour chaque v dans graphe
distance[v] = infini
q = ajouter(q, v)
distance[s] = 0
tant que non_vide(q)
// sélection de u t.q. la distance dans q est min
u = min(q, distance)
si u == t // on a atteint la cible
retourne distance
q = remove(q, u)
// voisin de u encore dans q
pour chaque v dans voisinage(u, q)
// on met à jour la distance du voisin en passant par u
n_distance = distance[u] + w(u, v)
si n_distance < distance[v]
distance[v] = n_distance
retourne distance
```
# Algorithme de Dijkstra
* Cet algorithme, nous donne le plus court chemin mais...
* ne nous donne pas le chemin!
## Comment modifier l'algorithme pour avoir le chemin?
. . .
* Pour chaque nouveau noeud à visiter, il suffit d'enregistrer d'où on est venu!
* On a besoin d'un tableau `precedent`.
## Modifier le pseudo-code ci-dessus pour ce faire (3min matrix)
# Algorithme de Dijkstra
\footnotesize
```C
tab, tab dijkstra(graph, s, t)
pour chaque v dans graphe
distance[v] = infini
precedent[v] = indéfini
q = ajouter(q, v)
distance[s] = 0
tant que non_vide(q)
// sélection de u t.q. la distance dans q est min
u = min(q, distance)
si u == t
retourne distance
q = remove(q, u)
// voisin de u encore dans q
pour chaque v dans voisinage(u, q)
n_distance = distance[u] + w(u, v)
si n_distance < distance[v]
distance[v] = n_distance
precedent[v] = u
retourne distance, precedent
```
# Algorithme de Dijkstra
## Comment reconstruire un chemin ?
. . .
```C
pile parcours(precedent, s, t)
sommets = vide
u = t
// on a atteint t ou on ne connait pas de chemin
si u != s && precedent[u] != indéfini
tant que vrai
sommets = empiler(sommets, u)
u = precedent[u]
si u == s // la source est atteinte
retourne sommets
retourne sommets
```
# Algorithme de Dijkstra amélioré
## On peut améliorer l'algorithme
* Avec une file de priorité!
## Une file de priorité est
* Une file dont chaque élément possède une priorité,
* Elle existe en deux saveurs: `min` ou `max`:
* File `min`: les éléments les plus petits sont retirés en premier.
* File `max`: les éléments les plus grands sont retirés en premier.
* On regarde l'implémentation de la `max`.
## Comment on fait ça?
. . .
* On insère les éléments à haute priorité tout devant dans la file!
# Les files de priorité
## Trois fonction principales
```C
booléen est_vide(element) // triviale
element enfiler(element, data, priorite)
data defiler(element)
rien changer_priorite(element, data, priorite)
nombre priorite(element) // utilitaire
```
## Pseudo-implémentation: structure (1min)
. . .
```C
struct element
data
priorite
element suivant
```
# Les files de priorité
## Pseudo-implémentation: enfiler (2min)
. . .
```C
element enfiler(element, data, priorite)
n_element = creer_element(data, priorite)
si est_vide(element)
retourne n_element
si priorite(n_element) > priorite(element)
n_element.suivant = element
retourne n_element
sinon
tmp = element
prec = element
tant que !est_vide(tmp) && priorite < priorite(tmp)
prec = tmp
tmp = tmp.suivant
prev.suivant = n_element
n_element.suivant = tmp
retourne element
```
# Les files de priorité
## Pseudo-implémentation: defiler (2min)
. . .
```C
data, element defiler(element)
si est_vide(element)
retourne AARGL!
sinon
tmp = element.data
n_element = element.suivant
liberer(element)
retourne tmp, n_element
```
# Algorithme de Dijkstra avec file de priorité min