Cours3

publicité
Algorithme Combinatoire
Décomposition d’un graphe (partie 2)
Les ponts de Königsberg, résolu par Euler
Liens Wikipédia :
Le problème consiste à déterminer s'il existe ou non une promenade dans les
rues de Königsberg permettant, à partir d'un point de départ au choix, de
passer une et une seule fois par chaque pont, et de revenir à son point de
départ, étant entendu qu'on ne peut traverser le Pregel qu'en passant sur les
ponts.
La condition nécessaire pour
satisfaire cet algorithme est d’avoir
un nombre pair de degré entrant et
un nombre pair de degré sortant
pour chaque sommet, afin de
pouvoir partir d’un sommet, passer
par tous les ponts une fois
exactement et revenir au sommet
initial
On veut passer par chaque arrête une seule fois
Pour chaque sommet on regarde le degré : tps
polynomial
 Caractérisation des graph eulérien
Schéma eulérien : aller à tous les sommets en
passant une fois exactement par arête : si on a
un nombre d’arête impair on doit le rendre pair
Exemple d’exercice Eulérien
On a un degré pair pour chaque sommet, une solution
existe donc
Calcul du temps : on supprime une
arête a chaque sommet :
Chemin en partant de B : BACB
Ici on est bloqué, on supprime donc et on le met dans
la liste des isolés : B
Si on continu donc : BACBDEFDAFC
Comme C est donc bloqué, on l’ajoute a la liste des
isolés : BC
Et on continue jusqu’à être définitivement bloqué :
Isolées :BCFADFEDCAB
Grâce à ça, on obtient la liste désiré en inversant celle
des isolées : BACDEFDAFCB
On peut donc mettre un sens pour les flèches (en rouge
sur le schéma)
A : BCDF
B : AC
C : ABDF
D : ACFE
E : DF
F : ACDE
La suppression de chaque arête prends un temps constant, c’est donc un algorithme
super master
Exo 1 : Trouver l’algorithme pour un graph Eulérien (le schéma 3)
𝑅 = [ ] → 𝑙𝑖𝑠𝑡𝑒 𝑑𝑒𝑠 𝑖𝑠𝑜𝑙é𝑠
𝑄. 𝑎𝑝𝑝𝑒𝑛𝑑(𝑢)
𝑤ℎ𝑖𝑙𝑒 𝑄 ∶
𝑧 = 𝑄. 𝑡𝑜𝑝()
𝑖𝑓 𝑎𝑑𝑗[𝑧] == [ ]
𝑅. 𝑖𝑛𝑠𝑒𝑟𝑡(0, 𝑧)
𝑄. 𝑝𝑜𝑝()
𝑒𝑙𝑠𝑒
𝑥 = 𝑎𝑑𝑗[𝑧]. 𝑝𝑜𝑝()
𝑎𝑗𝑑[𝑥]. 𝑟𝑒𝑚𝑜𝑣𝑒(𝑧)
𝑄. 𝑝𝑢𝑠ℎ(𝑥)
Tri topologique
Exemple : on suit un curseur informatique, chaque étudiant doit connaître java, scheme,
algo, compile, python, lang, OFI, C
On doit avoir des prérequis
Voici le schéma :
On cherche donc à obtenir :
On cherche une arête qui va de gauche à droite
Tri topologique : linéarisé les graphes, donc pas d’arête de droite à gauche :
(𝑥1 , … 𝑥𝑛 ) 𝑡𝑞 ∀ (𝑥𝑖 , 𝑥𝑗 ) ∈ 𝐸 → 𝑖 < 𝑗
Donc si le tri est cyclique, il ne peut être topologique
Topologique implique acyclique
On a donc que les degrés entrants
 SABDCE
 SBACDE
Construire l’algorithme du tri topologique :
On utilise un parcourt en profondeur
𝑄 = {𝑢 𝑓𝑜𝑟 𝑢 𝑖𝑛 𝑎𝑗𝑑 𝑖𝑓 𝐷+ [𝑢] == 0}
𝐿 =[]
𝑎=1
𝑤ℎ𝑖𝑙𝑒 𝑄 ∶
𝑧 = 𝑄. 𝑝𝑜𝑝()
𝐿 = 𝐿. 𝑎𝑝𝑝𝑒𝑛𝑑(𝑧)
𝑎 += 1
𝑓𝑜𝑟 𝑥 𝑖𝑛 𝑎𝑑𝑗[𝑧]:
𝐷+ [𝑥] −= 1
if 𝐷+ [𝑥] == 0
𝑄. 𝑎𝑝𝑝𝑒𝑛𝑑(𝑥)
𝑎 = 𝐿−1
Avec les lignes en rouge ajouté, l’algorithme est super master :
si on retrouve 𝑎 = 𝐿 − 1 sinon on a un cycle
Existe-t-il un sommet qui n’a pas de degré entrant ? oui
Si le graphe est acyclique, on supprime un sommet de degré entrant zéro, le graphe en
résultant le sera-t-il ? oui, il prend les propriétés précédentes
Supposons un graphe avec aucun sommet de degré zero, comment est-il ? Il est donc
cyclique
Exemple :
A = BCDE
B = AC
C = ABDE
D =AC
E = AC
-> BACDE -> on obtient une liste
vide = recherche en profondeur
DFS = recherche ne profondeur = depth first search
𝑢 = [0 𝑓𝑜𝑟 𝑣 𝑖𝑛 𝐺]
𝑄. 𝑝𝑢𝑠ℎ(𝑢)
𝑀[𝑢] = 1
𝑓𝑜𝑟 𝑥 𝑖𝑛 𝑎𝑑𝑗[𝑧] :
𝑖𝑓 𝑀[𝑥] == 0
𝐷𝐹𝑆𝑅 (𝐺, 𝑉)
Algorithme du dernier schéma : recherche en profondeur
𝑀[𝑢] = 1
𝑄. 𝑎𝑝𝑝𝑒𝑛𝑑(𝑢)
𝑤ℎ𝑖𝑙𝑒 𝑄 ∶
𝑧 = 𝑄. 𝑡𝑜𝑝()
𝑖𝑓 𝑎𝑑𝑗[𝑧] = []
𝑄. 𝑝𝑜𝑝()
𝑓𝑜𝑟 𝑥 𝑖𝑛 𝑎𝑑𝑗[𝑧]
𝑎𝑑𝑗[𝑧]. 𝑟𝑒𝑚𝑜𝑣𝑒(𝑥)
𝑖𝑓 𝑀[𝑥] == 0
𝑀[𝑥] = 1
𝑄. 𝑝𝑢𝑠ℎ(𝑥)
𝑏𝑟𝑒𝑎𝑘
Modifier l’algorithme pour qu’il test si le graph à un cycle ou pas
𝐿. 𝑎𝑝𝑝𝑒𝑛𝑑 (𝑢)
𝑀[𝑢] = 1
𝑓𝑜𝑟 𝑥 𝑖𝑛 𝐺[𝑧]
𝑖𝑓 𝑀[𝑥] == 0
𝐷𝐹𝑆(𝐺, 𝑉)
𝑒𝑙𝑠𝑒
𝑟𝑒𝑚𝑒𝑚𝑏𝑒𝑟(𝑥, 𝐿)
Téléchargement