diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 797acea53eb091cf5b30518802c3073f544adeed..0000000000000000000000000000000000000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="RunConfigurationProducerService">
-    <option name="ignoredProducers">
-      <set>
-        <option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
-      </set>
-    </option>
-  </component>
-</project>
\ No newline at end of file
diff --git a/README.md b/README.md
index 80dffb8ec53ef0a425f2fa1835e4696a3ed73816..a58fd2b4820ad3e99ec5dc9114b9ca26d1d1c152 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,454 @@
 # TP3
-ici votre rapport
+
+
+Ce projet a été réalisé par **Sarah Cherchem** et **Celia Arezki**.
+
+## Algorithmes Réalisés :
+
+
+Nous avons implémenté plusieurs algorithmes d'arbres couvrants aléatoires, dont certains sont 
+présentés de manière similaire mais avec des variantes intéressantes. Voici les algorithmes que nous a
+vons traités dans ce projet :
+
+### 3.1 Arbres couvrants de poids minimum aléatoire
+Un algorithme simple pour obtenir un arbre couvrant aléatoire. L'idée est de :
+1. Attribuer un poids aléatoire à chaque arête dans l'intervalle [0,1].
+2. Retourner un arbre couvrant de poids minimum en utilisant l'algorithme de **Prim** ou **Kruskal**.
+ (on a utilisé Prim)
+
+### 3.2 Parcours aléatoire
+Effectuer un parcours du graphe en partant d’un sommet aléatoire et choisir les arcs de la frontière 
+au hasard pour définir un arbre couvrant.
+
+### 3.3 Insertion aléatoire d’arêtes
+Construire un arbre couvrant en insérant des arêtes aléatoires, en s'assurant que chaque insertion
+ne crée pas de cycle, à l'aide de structures de données **Union-Find**.
+
+### 3.4 Algorithme d’Aldous-Broder
+Cet algorithme consiste à effectuer une marche aléatoire sur le graphe, où l'arbre couvrant est
+constitué des arêtes qui ont permis d'atteindre chaque sommet pour la première fois.
+
+### 3.5 Par contraction d’arêtes
+Choisir une arête aléatoire, la contracter, puis chercher un arbre couvrant dans le graphe contracté. 
+Cette méthode peut créer des boucles ou des arêtes parallèles, il est donc important de les gérer correctement.
+
+### 3.6 Algorithme de Wilson
+Construire un arbre couvrant en effectuant des marches aléatoires depuis des sommets extérieurs
+à l'arbre jusqu'à ce qu'ils atteignent un sommet de l'arbre. Ces chemins sont ajoutés à l'arbre.
+
+
+
+### 3.8 Par suppression de cycles
+Construire un arbre couvrant en choisissant aléatoirement des arêtes incidentes à chaque sommet et
+en supprimant les cycles qui peuvent apparaître. ### Pour cette algorithme nous avons commencé son implémentation
+cependant il reste quelque erreur lié à la logique.
+
+
+
+
+
+
+## Contenu du projet
+Le projet contient les éléments suivants :
+
+1. **Classes principales**
+   - **Graph** : Structure de base pour représenter les graphes non orientés.
+   - **Edge** et **Arc** : Représentent respectivement les arêtes et les arcs orientés.
+   - **RootedTree** : Permet d’analyser un arbre enraciné (diamètre, centre, indice de Wiener, etc.).
+   - **UnionFind** : Structure de données pour la gestion des ensembles disjoints, utile dans les algorithmes comme la contraction ou l’insertion aléatoire.
+
+2. **Algorithmes de génération d'arbres couvrants**
+   - **Aldous-Broder** : Utilise une marche aléatoire pour construire un arbre couvrant uniforme.
+   - **Prim** : Génère un arbre de poids minimum avec des poids aléatoires.
+   - **Wilson** : Marche aléatoire modifiée pour générer des arbres couvrants uniformément.
+   - **Insertion aléatoire** : Ajoute des arêtes aléatoires sans former de cycles.
+   - **Contraction d'arêtes** : Contracte des arêtes aléatoires tout en maintenant la connectivité.
+   - **Parcours aléatoire (RandomSearch)** : Parcours aléatoire à partir d'un sommet pour construire l'arbre.
+   - **Suppression de cycles** : Supprime les cycles formés par des arêtes aléatoirement choisies.
+
+3. **Types de graphes pour les tests**
+   - **Grille** : Graphe en forme de grille.
+   - **Complet** : Graphe où tous les sommets sont connectés.
+   - **Erdős-Rényi** : Graphe généré avec une probabilité de connexion entre les sommets.
+   - **Lollipop** : Graphe combinant un cycle et un chemin.
+
+4. **Visualisation et statistiques**
+   - **Labyrinth** : Visualisation des arbres couvrants sous forme de labyrinthe.
+   - **Stats** : Calcul de métriques telles que le diamètre moyen, l’indice de Wiener, et le nombre de feuilles.
+
+
+
+
+1 - AbstractArbreCouvrant (Classe abstraite) :
+
+
+La classe AbstractArbreCouvrant sert de base pour toutes les implémentations d'algorithmes d'arbres couvrants.
+Elle contient les éléments communs qui seront utilisés par toutes les classes qui en héritent. Voici ses 
+principales caractéristiques :
+
+Attributs :
+
+protected final Graph graph: Il s'agit d'un objet Graph qui représente le graphe sur 
+lequel l'algorithme doit être exécuté. Ce graphe est passé en paramètre lors de la création
+de l'objet AbstractArbreCouvrant.
+
+
+protected final Random generator: Un générateur de nombres aléatoires utilisé dans certaines 
+implémentations d'algorithmes (comme pour l'initialisation des poids dans l'algorithme de Prim).
+protected final Set<Edge> arbre: Un ensemble qui contient les arêtes de l'arbre couvrant. Ce set 
+est commun à toutes les implémentations d'algorithmes, et les arêtes de l'arbre sont ajoutées au 
+fur et à mesure de l'exécution de l'algorithme.
+
+
+2. ArbreCouvrant (Interface)
+   Cette interface définit le contrat que toutes les implémentations d'algorithmes d'arbres
+   couvrants doivent respecter. Elle contient une seule méthode :
+  - Set<Edge> arbreCouvrant() : Cette méthode doit être implémentée par toutes les classes 
+    dérivées pour générer un arbre couvrant du graphe. Elle retourne un ensemble d'arêtes qui composent
+    l'arbre couvrant.
+3. Prim (Algorithme de Prim)
+   La classe Prim hérite de AbstractArbreCouvrant et implémente l'algorithme de Prim pour générer
+   un arbre couvrant minimum dans un graphe. Voici les éléments clés de l'implémentation :
+
+Attributs :
+
+private final Map<Edge, Double> poids: Une carte qui associe à chaque arête du graphe un poids 
+aléatoire. Ces poids sont utilisés pour choisir l'arête de poids minimal à chaque étape de l'algorithme de Prim.
+private final PriorityQueue<Edge> queue: Une file de priorité qui contient les arêtes du graphe, triées par 
+leur poids. Cela permet de toujours récupérer l'arête de poids minimal de manière efficace.
+
+Méthodes :
+
+- genererPoidsAleatoires() : Cette méthode attribue un poids aléatoire à chaque arête du graphe. 
+Elle génère un nombre aléatoire entre 0 et 1 pour chaque arête. Le poids est stocké dans la carte poids.
+Le poids des arêtes est normalisé pour qu'il soit dans l'intervalle [0, 1]. Si le nombre d'arêtes
+est supérieur à 500, un calcul basé sur le cube du nombre d'arêtes est utilisé pour définir une
+borne supérieure au poids aléatoire.
+- arbreCouvrant() : Cette méthode implémente l'algorithme de Prim pour générer un arbre 
+couvrant. Voici les étapes de l'algorithme :
+- Choisir un sommet de départ : L'algorithme commence avec un sommet arbitraire (dans ce cas, le sommet 0).
+Ajouter les arêtes sortantes du sommet au queue : Toutes les arêtes connectées au 
+ sommet de départ sont ajoutées à la file de priorité.
+Boucle principale : Tant que la queue n'est pas vide, l'algorithme extrait l'arête de poids 
+minimal et vérifie si le sommet de destination de cette arête a déjà été visité. Si ce n'est pas le cas,
+l'arête est ajoutée à l'arbre couvrant, et toutes les arêtes sortantes du sommet de destination sont
+ajoutées à la file de priorité.
+Retourner l'arbre couvrant : Une fois que l'arbre couvrant a été généré, il est retourné sous forme
+d'un ensemble d'arêtes.
+
+
+2- Insertion
+La classe Insertion implémente un algorithme de génération d'arbre couvrant en utilisant une 
+approche de type Kruskal avec un tirage aléatoire des arêtes. Elle évite la formation de cycles
+grâce à la structure de données Union-Find. L'algorithme procède comme suit :
+
+Mélange aléatoirement les arêtes du graphe.
+Ajoute une arête à l'arbre couvrant si elle ne forme pas de cycle, en vérifiant 
+la connectivité des sommets avec Union-Find.
+Répète ce processus jusqu'à ce que l'arbre couvrant contienne 𝑉 − 1 arêtes, où
+V est le nombre de sommets du graphe.
+Cette approche est simple et efficace pour la génération d'arbres couvrants dans des graphes non orientés.
+
+3- AldousBroder
+La classe AldousBroder implémente un algorithme de génération d'arbre couvrant basé sur la marche aléatoire.
+L'algorithme fonctionne de la manière suivante :
+
+Un sommet initial est choisi aléatoirement.
+L'algorithme effectue une marche aléatoire en sélectionnant des arcs sortants du sommet actuel jusqu'à ce
+que tous les sommets aient été visités.
+Lorsqu'un nouveau sommet est visité pour la première fois, l'arête menant à ce sommet est ajoutée à l'arbre 
+couvrant.
+L'algorithme continue cette marche jusqu'à ce que l'arbre couvrant contienne tous les sommets du graphe.
+Cet algorithme est basé sur la marche aléatoire de type Aldous-Broder et garantit la construction d'un
+arbre couvrant. Il est particulièrement efficace dans les graphes aléatoires.
+
+4- Wilson :
+La classe Wilson implémente un algorithme de génération d'arbre couvrant appelé algorithme de Wilson.
+Cet algorithme est basé sur la marche aléatoire, et il est plus spécifique que d'autres algorithmes comme 
+celui de Prim ou Kruskal. Voici une explication détaillée du fonctionnement de cet algorithme :
+
+Description de l'algorithme de Wilson :
+
+Initialisation :
+
+L'algorithme commence avec un ensemble de sommets visités (sommetVisite) qui est initialement vide.
+Il crée une map (outArc) pour stocker les arêtes rencontrées lors des marches aléatoires.
+Itérations sur les sommets :
+
+L'algorithme traite les sommets du graphe un par un, en choisissant d'abord un sommet de départ (ici, 
+les sommets sont triés en fonction de leur degré, du plus grand au plus petit).
+Si un sommet n'a pas encore été visité, il commence une marche aléatoire depuis ce sommet pour rejoindre 
+un sommet déjà visité.
+
+Marche aléatoire :
+
+À chaque étape de la marche, un sommet est choisi au hasard parmi les voisins du sommet courant.
+L'algorithme enregistre les arêtes empruntées dans une map (outArc) pour pouvoir retracer le chemin
+lorsque la marche atteint un sommet déjà visité.
+
+Retour sur le chemin parcouru :
+
+Une fois qu'une marche atteint un sommet déjà visité, l'algorithme commence à retracer le chemin 
+parcouru en marquant chaque sommet comme visité et en ajoutant chaque arête à l'arbre couvrant (arbre).
+
+Terminaison :
+
+Ce processus continue jusqu'à ce que tous les sommets aient été visités, ce qui garantit que l'arbre 
+couvrant contient tous les sommets du graphe.
+Points importants :
+Marche aléatoire : La caractéristique de l'algorithme de Wilson repose sur la marche aléatoire qui démarre 
+à un sommet choisi au hasard et avance jusqu'à ce qu'elle atteigne un sommet déjà visité.
+Complexité : L'algorithme de Wilson est un peu plus complexe que les algorithmes de Prim ou Kruskal, mais 
+il garantit un arbre couvrant de manière probabiliste.
+
+
+5- Recherche Aléatoire :
+La classe RandomSearch implémente un algorithme de recherche aléatoire pour générer un arbre couvrant. 
+Voici une explication détaillée du fonctionnement de cet algorithme :
+
+Description générale de l'algorithme :
+L'algorithme RandomSearch fonctionne en explorant le graphe de manière aléatoire. Voici les étapes principales :
+
+Initialisation :
+
+Un sommet de départ est choisi aléatoirement parmi les sommets du graphe.
+Ce sommet est ajouté à l'ensemble des sommets visités.
+La liste des arcs à explorer (frontier) est initialement vide, mais elle est remplie avec 
+les arcs sortants du sommet de départ.
+
+
+Exploration aléatoire :
+
+L'algorithme fonctionne tant qu'il reste des arcs dans la liste frontier à explorer.
+À chaque itération, un arc est choisi au hasard parmi ceux disponibles dans frontier (la liste 
+est mélangée aléatoirement avec Collections.shuffle).
+Si l'arc mène à un sommet qui n'a pas encore été visité, cet arc est ajouté à l'arbre couvrant, et 
+ce sommet est marqué comme visité.
+Tous les arcs sortants du sommet destination de l'arc choisi sont ajoutés à la liste frontier pour être
+explorés plus tard.
+
+Terminaison :
+
+L'algorithme continue jusqu'à ce que tous les sommets aient été visités. Cela garantit que l'arbre couvrant
+contient tous les sommets du graphe, mais peut contenir un nombre d'arêtes supérieur au minimum nécessaire.
+
+
+6- Contraction :
+1. ContractionGraph :
+   Cette classe est responsable de la gestion du graphe après la contraction des arêtes. 
+   Lorsqu'une arête est contractée, elle relie deux sommets ensemble en une seule entité (un sommet "combiné"),
+   supprimant ainsi l'arête contractée et réarrangeant le graphe.
+
+Attributs principaux :
+
+incidence : Une liste de listes (LinkedList<Integer>). Chaque liste correspond à un sommet et contient 
+les indices des arêtes incidentes à ce sommet.
+extrimite1 et extrimite2 : Listes qui contiennent respectivement les sommets de départ et d'arrivée pour
+chaque arête dans le graphe.
+initialEdges : Liste des arêtes initiales du graphe.
+Méthodes principales :
+ContractionGraph(Graph graph) : Le constructeur initialise les listes incidence, extrimite1, extrimite2 
+et initialEdges en parcourant toutes les arêtes du graphe. Il ajoute chaque arête à ces listes et associe 
+les indices des arêtes aux sommets correspondants dans incidence.
+
+boucle(int indexEdge) : Cette méthode vérifie si une arête est une boucle (c'est-à-dire si elle relie un 
+sommet à lui-même). Elle retourne true si les deux extrémités de l'arête sont le même sommet.
+
+contract(int edgeIndex) : Cette méthode contracte une arête spécifiée par edgeIndex. Si l'arête n'est pas 
+une boucle, elle relie les deux sommets qu'elle connecte. Tous les arcs incident au deuxième sommet sont 
+réajustés pour pointer vers le premier sommet, et les arêtes sont modifiées en conséquence pour refléter 
+cette contraction dans la structure de données du graphe.
+
+getInitialEdges(), getExtrimite1(), getExtrimite2() : Ces méthodes retournent respectivement les listes 
+des arêtes initiales et des extrémités des arêtes. Elles sont utilisées pour obtenir des informations sur 
+le graphe initial après la contraction.
+
+2. Contraction :
+   Cette classe implémente l'algorithme de contraction d'arêtes pour créer un arbre couvrant. Elle utilise
+3. ContractionGraph pour gérer les contractions des arêtes et UnionFind pour détecter et éviter les cycles 
+4. lors de la construction de l'arbre couvrant.
+
+Attributs principaux :
+contractionGraph : Instance de la classe ContractionGraph utilisée pour gérer le graphe après contraction 
+des arêtes.
+unionFind : Instance de l'algorithme Union-Find (ou Disjoint Set Union), utilisée pour suivre et gérer les 
+connexions entre les sommets et éviter de former des cycles dans l'arbre couvrant.
+nodes : Un tableau de Node, où chaque Node contient des informations sur la profondeur et la hauteur de
+chaque sommet. Cependant, ces informations ne sont pas utilisées dans cette version du code.
+Méthodes principales :
+Contraction(Graph graph) : Le constructeur initialise les objets contractionGraph (pour la gestion des 
+contractions) et unionFind (pour suivre les connexions entre les sommets). Il initialise également le tableau
+nodes, bien qu'il ne soit pas utilisé dans cette version du code.
+
+arbreCouvrant() : Cette méthode implémente l'algorithme de contraction pour générer un arbre couvrant. 
+Les étapes sont les suivantes :
+
+Initialisation des arêtes : Une liste edges est remplie avec les indices des arêtes du graphe.
+Mélange des arêtes : Les arêtes sont mélangées de manière aléatoire pour assurer que l'algorithme ne 
+suit pas un ordre fixe.
+Parcours des arêtes : Pour chaque arête, si l'arête est une boucle, elle est ignorée. Si les sommets 
+reliés par l'arête sont déjà connectés dans l'arbre (vérifié par unionFind.find()), l'arête est ignorée
+pour éviter les cycles.
+Ajout de l'arête à l'arbre couvrant : Si l'arête relie deux sommets non connectés, elle est ajoutée à 
+l'arbre couvrant.
+Union des sommets : Les sommets reliés par l'arête sont unis (avec unionFind.union()).
+Contraction de l'arête : L'arête est contractée dans le graphe (avec contractionGraph.contract()).
+À la fin, l'algorithme retourne l'ensemble arbre, qui contient les arêtes de l'arbre couvrant généré.
+
+Classe interne Node :
+Cette classe représente un sommet avec deux propriétés :
+
+depth : La profondeur du sommet dans l'arbre. Cependant, dans ce code, elle reste à 0 et n'est pas utilisée.
+height : La hauteur du sommet. Comme la profondeur, elle n'est pas utilisée ici.
+Interaction entre les classes :
+ContractionGraph gère la structure interne du graphe après chaque contraction d'arête. Elle suit les 
+modifications des arêtes et des sommets, en ajustant les indices et en évitant de créer des boucles.
+
+Contraction utilise ContractionGraph pour manipuler le graphe en cours et pour générer l'arbre couvrant. 
+Elle se repose également sur UnionFind pour garantir que l'algorithme ne crée pas de cycles en ajoutant 
+des arêtes.
+
+Comparaison des résultats pour chaque algorithme :
+1. Algorithme Prim :
+   Excentricité moyenne : 70.30
+   Indice de Wiener moyen : 1,599,399,905
+   Diamètre moyen : 263
+   Nombre moyen de feuilles : 1,228
+   Nombre moyen de sommets de degré 2 : 2,729
+   Temps de calcul moyen : 38,686,424 ms
+
+![Algorithme Aléatoire de prim](resources/Prim.png)
+
+
+2. Algorithme Aldous :
+
+   Excentricité moyenne : 112.54
+   Indice de Wiener moyen : 2,219,478,278
+   Diamètre moyen : 424
+   Nombre moyen de feuilles : 1,514
+   Nombre moyen de sommets de degré 2 : 2,330
+   Temps de calcul moyen : 38,690,744 ms
+
+
+![Algorithme Aldous-Broder](resources/AldousBroder.png)
+
+
+3. Algorithme Insertion :
+   Excentricité moyenne : 104.01
+   Indice de Wiener moyen : 2,038,044,944
+   Diamètre moyen : 387
+   Nombre moyen de feuilles : 1,583
+   Nombre moyen de sommets de degré 2 : 2,226
+   Temps de calcul moyen : 38,694,069 ms
+
+![Algorithme Par Insertion](resources/Insertion.png)
+
+
+4. Recherche Aléatoire :
+   Excentricité moyenne : 53.80
+   Indice de Wiener moyen : 1,193,672,822
+   Diamètre moyen : 207
+   Nombre moyen de feuilles : 1,670
+   Nombre moyen de sommets de degré 2 : 2,084
+   Temps de calcul moyen : 38,698,474 ms
+
+   ![Algorithme de recherche aléatoire](resources/RandomSearch.png)
+
+5. Algorithme Contraction :
+
+   Excentricité moyenne : 106.99
+   Indice de Wiener moyen : 2,081,870,127
+   Diamètre moyen : 424
+   Nombre moyen de feuilles : 1,577
+   Nombre moyen de sommets de degré 2 : 2,234
+   Temps de calcul moyen : 38,704,749 ms
+
+![Algorithme De Contraction](resources/Contraction.png)
+
+
+6. Algorithme Wilson :
+   Excentricité moyenne : 127.26
+   Indice de Wiener moyen : 2,487,683,163
+   Diamètre moyen : 500
+   Nombre moyen de feuilles : 1,515
+   Nombre moyen de sommets de degré 2 : 2,340
+   Temps de calcul moyen : 38,709,040 ms
+
+
+![Algorithme de wilson](resources/Wilson.png)
+
+Analyse des résultats :
+Excentricité :
+
+- **L'algorithme Recherche aléatoire reste celui avec la plus basse excentricité moyenne (53.80), indiquant 
+une meilleure uniformité dans la distribution des sommets.
+Wilson génère l'arbre avec la plus grande excentricité (127.26), suggérant des arbres plus "étendus"**
+- **Indice de Wiener :
+Wilson a l'indice de Wiener le plus élevé (2,487,683,163), ce qui montre que les arbres générés par Wilson ont
+des distances plus longues entre certaines paires de sommets.
+L'algorithme Recherche aléatoire a l'indice de Wiener le plus bas (1,193,672,822), indiquant des arbres avec des 
+distances plus courtes en moyenne**.
+
+-**Diamètre :
+Wilson génère des arbres avec le diamètre le plus élevé (500), ce qui correspond à l'excentricité et à l'indice de Wiener élevés.
+Recherche aléatoire a le diamètre le plus bas (207), correspondant à sa faible excentricité et indice de Wiener**
+
+-**Nombre de feuilles :
+L'algorithme Recherche aléatoire génère le plus grand nombre de feuilles (1,670), suggérant des arbres plus ramifiés.
+Aldous a le nombre de feuilles le plus faible (1,514), indiquant des arbres plus concentrés.**
+-**Nombre de sommets de degré 2 :
+Prim a le plus grand nombre de sommets de degré 2 (2,729), ce qui pourrait refléter des arbres plus équilibrés.
+Wilson et Contraction ont des résultats similaires (2,340 et 2,234), avec un nombre modéré de sommets de degré 2.**
+
+
+-**Temps de calcul :
+Les temps de calcul pour tous les algorithmes sont relativement proches (environ 38.7 millions de millisecondes 
+en moyenne), avec une légère variation qui pourrait être influencée par les spécificités des algorithmes et de 
+l'implémentation.**
+
+### Conclusion :
+Recherche aléatoire semble générer des arbres avec des caractéristiques plus équilibrées (faible excentricité, 
+faible indice de Wiener et diamètre), et un plus grand nombre de feuilles.
+Wilson génère des arbres plus étendus avec un diamètre plus élevé, une excentricité plus grande et un indice de
+Wiener élevé.
+Contraction et Aldous génèrent des arbres plus proches en termes de métriques, mais Wilson et Prim se distinguent
+par des arbres ayant un diamètre plus large et une plus grande dispersion des sommets.
+Les algorithmes comme Prim et Aldous semblent produire des arbres plus réguliers tandis que Wilson et Contraction 
+génèrent des arbres plus "étendus", avec des métriques plus élevées.
+
+
+
+
+
+
+## Comparaison des algorithmes
+
+### Métriques évaluées
+- **Diamètre moyen** : Distance maximale entre deux sommets.
+- **Indice de Wiener** : Somme des distances entre toutes les paires de sommets.
+- **Distribution des degrés** : Proportion des sommets ayant un degré donné.
+
+### Observations
+- **Aldous-Broder** : Produit des arbres couvrants uniformément mais peut être lent sur de grands graphes.
+- **Prim** : Rapide pour les graphes denses, mais les poids aléatoires influencent les résultats.
+- **Wilson** : Garantit une distribution uniforme tout en étant plus efficace qu'Aldous-Broder.
+- **Insertion aléatoire** : Simple à implémenter mais sensible à l'ordre des arêtes.
+- **Contraction** : Efficace mais plus complexe à coder.
+- **Suppression de cycles** : Produit des arbres non uniformes avec un bon compromis entre qualité et performance.
+
+---
+
+## Limitations
+- Certains algorithmes (par ex. contraction d'arêtes) peuvent être inefficaces pour les très grands graphes.
+- Les visualisations sont limitées à certains types de graphes comme les grilles.
+
+
+## Ressources utilisées
+
+- [PDF - Math.ENS.PSL](chrome-extension://efaidnbmnnnibpcajpcglclefindmkaj/https://www.math.ens.psl.eu/shared-files/10422/?bureaux.pdf)
+- [Site d'Olivier Pons - Aldous-Broder](https://www.olivierpons.fr/labyrinthes/algorithme-daldous-broder/)
+- - Consigne du TP : [Lien vers le document fourni]
+- Documentation Java officielle : [https://docs.oracle.com/en/java/]
+- Structure Union-Find : [https://en.wikipedia.org/wiki/Disjoint-set_data_structure]
 
 
diff --git a/out/production/tp3-git/Graph/Arc.class b/out/production/tp3-git/Graph/Arc.class
new file mode 100644
index 0000000000000000000000000000000000000000..288a2e56b9c70572c27d79c76226d230581b829c
Binary files /dev/null and b/out/production/tp3-git/Graph/Arc.class differ
diff --git a/out/production/tp3-git/Graph/Edge.class b/out/production/tp3-git/Graph/Edge.class
new file mode 100644
index 0000000000000000000000000000000000000000..3714023ebb05072bd0a067e4feb091b5d8559393
Binary files /dev/null and b/out/production/tp3-git/Graph/Edge.class differ
diff --git a/out/production/tp3-git/Graph/Graph.class b/out/production/tp3-git/Graph/Graph.class
new file mode 100644
index 0000000000000000000000000000000000000000..d809e0c38eb9593738b10506151a3977ca1c59d3
Binary files /dev/null and b/out/production/tp3-git/Graph/Graph.class differ
diff --git a/out/production/tp3-git/Graph/RootedTree$Node.class b/out/production/tp3-git/Graph/RootedTree$Node.class
new file mode 100644
index 0000000000000000000000000000000000000000..0692e5e6788bac829ff47d8db1df42f59485c60e
Binary files /dev/null and b/out/production/tp3-git/Graph/RootedTree$Node.class differ
diff --git a/out/production/tp3-git/Graph/RootedTree.class b/out/production/tp3-git/Graph/RootedTree.class
new file mode 100644
index 0000000000000000000000000000000000000000..2375a9e9f7b7df869d7d43d5701510fb0363b7e0
Binary files /dev/null and b/out/production/tp3-git/Graph/RootedTree.class differ
diff --git a/out/production/tp3-git/GraphClasses/Complete.class b/out/production/tp3-git/GraphClasses/Complete.class
new file mode 100644
index 0000000000000000000000000000000000000000..660b632008c96e3208eba172b4ce1352b215a378
Binary files /dev/null and b/out/production/tp3-git/GraphClasses/Complete.class differ
diff --git a/out/production/tp3-git/GraphClasses/ErdosRenyi.class b/out/production/tp3-git/GraphClasses/ErdosRenyi.class
new file mode 100644
index 0000000000000000000000000000000000000000..3a3417eeb6f925354377fb1003136f22974cbea2
Binary files /dev/null and b/out/production/tp3-git/GraphClasses/ErdosRenyi.class differ
diff --git a/out/production/tp3-git/GraphClasses/Grid.class b/out/production/tp3-git/GraphClasses/Grid.class
new file mode 100644
index 0000000000000000000000000000000000000000..d31c739d685a5be1ab0f86cb6da8ea84090982dc
Binary files /dev/null and b/out/production/tp3-git/GraphClasses/Grid.class differ
diff --git a/out/production/tp3-git/GraphClasses/Lollipop.class b/out/production/tp3-git/GraphClasses/Lollipop.class
new file mode 100644
index 0000000000000000000000000000000000000000..5c5377578fbe4a289b18cbdcbf36e8ac8240bd14
Binary files /dev/null and b/out/production/tp3-git/GraphClasses/Lollipop.class differ
diff --git a/out/production/tp3-git/Graphics/Labyrinth.class b/out/production/tp3-git/Graphics/Labyrinth.class
new file mode 100644
index 0000000000000000000000000000000000000000..5376478c78c236af7097968d8f8304398b92cbd3
Binary files /dev/null and b/out/production/tp3-git/Graphics/Labyrinth.class differ
diff --git a/out/production/tp3-git/Main$Stats.class b/out/production/tp3-git/Main$Stats.class
new file mode 100644
index 0000000000000000000000000000000000000000..03a521f3d20941071b7fa9c2e240fbd9d6336fba
Binary files /dev/null and b/out/production/tp3-git/Main$Stats.class differ
diff --git a/out/production/tp3-git/Main.class b/out/production/tp3-git/Main.class
new file mode 100644
index 0000000000000000000000000000000000000000..bf550d1e2c9d24f22f8194d98ca808909a8f355e
Binary files /dev/null and b/out/production/tp3-git/Main.class differ
diff --git a/out/production/tp3-git/Makefile b/out/production/tp3-git/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ebb1dca2694c7a8ff6cb7bee78a3388e5dd8ed7a
--- /dev/null
+++ b/out/production/tp3-git/Makefile
@@ -0,0 +1,26 @@
+# Le nom de votre classe principale
+# Renommez si nécessaire
+MAINCLASS=Main
+## Le chemin vers où votre classe compilée est installée
+# Renommez si nécessaire
+INSTALLDIR=../out/production/TP3
+MAINDIR=$(dir $(subst .,/,$(MAINCLASS)))
+CLASSES=$(shell find $(INSTALLDIR)/$(MAINDIR) -name \*.class)
+
+compile: $(subst .,/,$(MAINCLASS)).class
+
+%.class: %.java
+	javac -g -d $(INSTALLDIR) *.java
+
+clean:
+	## Rien à faire, tout à été compilé et installé dans INSTALLDIR
+
+
+install:
+	## Rien à faire, tout à été compilé et installé dans INSTALLDIR
+
+cleanInstall:
+	rm $(subst $$,\$$,$(CLASSES))
+
+test:
+
diff --git a/out/production/tp3-git/RandomTreeAlgos/BreadthFirstSearch.class b/out/production/tp3-git/RandomTreeAlgos/BreadthFirstSearch.class
new file mode 100644
index 0000000000000000000000000000000000000000..1c2c79cb37ae64a1ff25061a68320522b2bfc684
Binary files /dev/null and b/out/production/tp3-git/RandomTreeAlgos/BreadthFirstSearch.class differ
diff --git a/out/production/tp3-git/Structures/ContractionGraph.class b/out/production/tp3-git/Structures/ContractionGraph.class
new file mode 100644
index 0000000000000000000000000000000000000000..ad4906be7dae348e8116f3f02be7760df5e490cf
Binary files /dev/null and b/out/production/tp3-git/Structures/ContractionGraph.class differ
diff --git a/out/production/tp3-git/TreesAlgo/AbstractArbreCouvrant.class b/out/production/tp3-git/TreesAlgo/AbstractArbreCouvrant.class
new file mode 100644
index 0000000000000000000000000000000000000000..988299124c618a82dffcc9f346ef553b96703380
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/AbstractArbreCouvrant.class differ
diff --git a/out/production/tp3-git/TreesAlgo/AldousBroder.class b/out/production/tp3-git/TreesAlgo/AldousBroder.class
new file mode 100644
index 0000000000000000000000000000000000000000..8c5342916222618860b3a54fcad215f5ddd4d820
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/AldousBroder.class differ
diff --git a/out/production/tp3-git/TreesAlgo/ArbreCouvrant.class b/out/production/tp3-git/TreesAlgo/ArbreCouvrant.class
new file mode 100644
index 0000000000000000000000000000000000000000..2c4c301851f9cc18ad57ff61b1ecd0e08566fe46
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/ArbreCouvrant.class differ
diff --git a/out/production/tp3-git/TreesAlgo/Contraction$Node.class b/out/production/tp3-git/TreesAlgo/Contraction$Node.class
new file mode 100644
index 0000000000000000000000000000000000000000..621f34e9d1ff5957b03b76400576beb518d1928b
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/Contraction$Node.class differ
diff --git a/out/production/tp3-git/TreesAlgo/Contraction.class b/out/production/tp3-git/TreesAlgo/Contraction.class
new file mode 100644
index 0000000000000000000000000000000000000000..8d91add90f69645de43972d7edc23e16cc60a812
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/Contraction.class differ
diff --git a/out/production/tp3-git/TreesAlgo/Insertion.class b/out/production/tp3-git/TreesAlgo/Insertion.class
new file mode 100644
index 0000000000000000000000000000000000000000..4ce03939ee2be7ae42821ae7ff26b4c50547ab61
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/Insertion.class differ
diff --git a/out/production/tp3-git/TreesAlgo/Prim.class b/out/production/tp3-git/TreesAlgo/Prim.class
new file mode 100644
index 0000000000000000000000000000000000000000..27f32abb69999f554dfe7ecb99ae0faf40745c78
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/Prim.class differ
diff --git a/out/production/tp3-git/TreesAlgo/RandomSearch.class b/out/production/tp3-git/TreesAlgo/RandomSearch.class
new file mode 100644
index 0000000000000000000000000000000000000000..68390f1088140e003c60b4ef0eab3b18dd03a7dd
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/RandomSearch.class differ
diff --git a/out/production/tp3-git/TreesAlgo/SuppressionCycle.class b/out/production/tp3-git/TreesAlgo/SuppressionCycle.class
new file mode 100644
index 0000000000000000000000000000000000000000..3409d947a9068baa04fb659127584d1239b2b779
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/SuppressionCycle.class differ
diff --git a/out/production/tp3-git/TreesAlgo/UnionFind.class b/out/production/tp3-git/TreesAlgo/UnionFind.class
new file mode 100644
index 0000000000000000000000000000000000000000..e0883abc29b4d053dcdbd48e6363676b5ae08802
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/UnionFind.class differ
diff --git a/out/production/tp3-git/TreesAlgo/Wilson.class b/out/production/tp3-git/TreesAlgo/Wilson.class
new file mode 100644
index 0000000000000000000000000000000000000000..011558f96f2e6be06b014adcfa246aa688e57a6c
Binary files /dev/null and b/out/production/tp3-git/TreesAlgo/Wilson.class differ
diff --git a/resources/AldousBroder.png b/resources/AldousBroder.png
new file mode 100644
index 0000000000000000000000000000000000000000..fdaf2a44f9541ab1e8a0ea49a516fb169dec5e84
Binary files /dev/null and b/resources/AldousBroder.png differ
diff --git a/resources/Contraction.png b/resources/Contraction.png
new file mode 100644
index 0000000000000000000000000000000000000000..32c0cef005ba8dda1635ca102aea30c51fd14cf1
Binary files /dev/null and b/resources/Contraction.png differ
diff --git a/resources/Insertion.png b/resources/Insertion.png
new file mode 100644
index 0000000000000000000000000000000000000000..9ed98b89b522cd8a6fa0ad92128ed2e30f5ae2d5
Binary files /dev/null and b/resources/Insertion.png differ
diff --git a/resources/Prim.png b/resources/Prim.png
new file mode 100644
index 0000000000000000000000000000000000000000..96d7d6324cd52032807ea2800253d71407066404
Binary files /dev/null and b/resources/Prim.png differ
diff --git a/resources/RandomSearch.png b/resources/RandomSearch.png
new file mode 100644
index 0000000000000000000000000000000000000000..5f9faf2cb8be020829db0be169897dfd33a8d776
Binary files /dev/null and b/resources/RandomSearch.png differ
diff --git a/resources/Wilson.png b/resources/Wilson.png
new file mode 100644
index 0000000000000000000000000000000000000000..dda28592a8ba0a9453f4c2cdc30dc4d2e5b775ae
Binary files /dev/null and b/resources/Wilson.png differ
diff --git a/resources/random.png b/resources/random.png
new file mode 100644
index 0000000000000000000000000000000000000000..ff9a0d384ef7800918ee99af3266a66c3fa5d4f4
Binary files /dev/null and b/resources/random.png differ
diff --git a/resources/search.png b/resources/search.png
new file mode 100644
index 0000000000000000000000000000000000000000..11fb0fd7682567b4d3bdf5088e94efc5f1a9e65f
Binary files /dev/null and b/resources/search.png differ
diff --git a/src/Graph/Edge.java b/src/Graph/Edge.java
index a439044e0a90abce9c8e5935f6aa888341e2faf4..52a339847588d735b7bf835a90fb73a3a3cbf2b7 100644
--- a/src/Graph/Edge.java
+++ b/src/Graph/Edge.java
@@ -4,7 +4,7 @@ public class Edge implements Comparable<Edge> {
 
 	public int source;
 	public int dest;
-	double weight;
+	public double weight;
 	
 	public Edge(int source, int dest, double weight) {
 		this.source = source;
diff --git a/src/Graph/Graph.java b/src/Graph/Graph.java
index 383b0b9b1017fb548676495aec7fdb5ec9badd40..3ed4c13b2f6dcc94ef6fb413b5e88be32ecbbfc0 100644
--- a/src/Graph/Graph.java
+++ b/src/Graph/Graph.java
@@ -2,6 +2,7 @@ package Graph;
 
 import java.util.ArrayList;
 import java.util.LinkedList;
+import java.util.List;
 
 
 public class Graph {
@@ -50,7 +51,10 @@ public class Graph {
     }
 
     public void addVertex(int vertex) {
+
         if (vertex >= upperBound) {
+
+
             throw new IllegalArgumentException("Sommet hors limites.");
         }
         while (incidency.size() <= vertex) {
@@ -59,6 +63,7 @@ public class Graph {
             outIncidency.add(new LinkedList<>());
         }
         order = Math.max(order, vertex + 1);
+
     }
 
 
@@ -112,7 +117,10 @@ public class Graph {
 
         edgeCardinality++;
     }
-
+    public int degreSommet(int vertex) {
+        // Le degré d'un sommet est simplement le nombre d'arêtes qui lui sont incidentes
+        return incidency.get(vertex).size();
+    }
 
     public Arc[] outEdges(int vertex) {
         if (!isVertex(vertex)) {
@@ -123,4 +131,90 @@ public class Graph {
         return outIncidency.get(vertex).toArray(new Arc[0]);
    }
 
+    public int getEdgeCardinality() {
+        return edgeCardinality;
+    }
+
+    public ArrayList<LinkedList<Edge>> getIncidency() {
+        return incidency;
+    }
+    public Edge getEdge(int u, int v) {
+        if (!isVertex(u) || !isVertex(v)) {
+            throw new IllegalArgumentException("Un des sommets n'existe pas.");
+        }
+
+        // Chercher l'arête entre u et v dans la liste des incidences du sommet u
+        for (Edge edge : incidency.get(u)) {
+            if (edge.oppositeExtremity(u) == v) {
+                return edge;
+            }
+        }
+        // Si l'arête n'existe pas, retourner null
+        return null;
+    }
+    public List<Integer> getVertices() {
+        List<Integer> vertices = new ArrayList<>();
+        for (int i = 0; i < order; i++) {
+            if (incidency.get(i) != null) {  // vérifier si le sommet existe
+                vertices.add(i);
+            }
+        }
+        return vertices;
+    }
+    public Graph copy() {
+        Graph newGraph = new Graph(this.upperBound); // Crée un nouveau graphe avec le même upperBound
+        newGraph.order = this.order;                // Copie l'ordre du graphe
+        newGraph.edgeCardinality = this.edgeCardinality; // Copie le nombre d'arêtes
+
+        // Copier les arêtes (incidency)
+        for (int i = 0; i < this.incidency.size(); i++) {
+            if (this.incidency.get(i) != null) {
+                LinkedList<Edge> newEdges = new LinkedList<>();
+                for (Edge edge : this.incidency.get(i)) {
+                    // Crée un nouvel Edge en copiant la source, destination et poids
+                    newEdges.add(new Edge(edge.getSource(), edge.getDest(), edge.weight));
+                }
+                newGraph.incidency.set(i, newEdges);
+            } else {
+                newGraph.incidency.set(i, null);
+            }
+        }
+
+        // Copier les arcs entrants (inIncidency)
+        for (int i = 0; i < this.inIncidency.size(); i++) {
+            if (this.inIncidency.get(i) != null) {
+                LinkedList<Arc> newInArcs = new LinkedList<>();
+                for (Arc arc : this.inIncidency.get(i)) {
+                    // Crée un nouvel Arc en copiant le support (Edge) et la direction (reversed)
+                    Edge edgeCopy = new Edge(arc.support.getSource(), arc.support.getDest(), arc.support.weight);
+                    newInArcs.add(new Arc(edgeCopy, arc.reversed));
+                }
+                newGraph.inIncidency.set(i, newInArcs);
+            } else {
+                newGraph.inIncidency.set(i, null);
+            }
+        }
+
+        // Copier les arcs sortants (outIncidency)
+        for (int i = 0; i < this.outIncidency.size(); i++) {
+            if (this.outIncidency.get(i) != null) {
+                LinkedList<Arc> newOutArcs = new LinkedList<>();
+                for (Arc arc : this.outIncidency.get(i)) {
+                    // Crée un nouvel Arc en copiant le support (Edge) et la direction (reversed)
+                    Edge edgeCopy = new Edge(arc.support.getSource(), arc.support.getDest(), arc.support.weight);
+                    newOutArcs.add(new Arc(edgeCopy, arc.reversed));
+                }
+                newGraph.outIncidency.set(i, newOutArcs);
+            } else {
+                newGraph.outIncidency.set(i, null);
+            }
+        }
+
+        return newGraph;
+    }
+
+
+
+
+
 }
diff --git a/src/Graph/RootedTree.java b/src/Graph/RootedTree.java
index 9793f129f8638680a5fde292419b256c33bc6167..a82097d74086b6ad4dcc7e4bfaf3d72b4238e22d 100644
--- a/src/Graph/RootedTree.java
+++ b/src/Graph/RootedTree.java
@@ -183,12 +183,13 @@ public class RootedTree {
 	
 	public int getRoot() { return root.vertex; }
 	
-	public int getHeight(int vertex) { 
-		return nodes[vertex].height;
+	public int getHeight(int vertex) {
+		 return nodes[vertex].height;
 	}
 	
 	public int getDepth(int vertex) {
-		return nodes[vertex].depth;
+		 return nodes[vertex].depth;
+
 	}
 	
 	public int getSubtreeSize(int vertex) {
@@ -274,14 +275,14 @@ public class RootedTree {
 			swapRootWith(root.maxHeightSon());
 		resetBfsOrdering();
 	}
-	
-	
+
+
 	private void createNode(Node nodes[], Arc arc) {
 		int son = arc.getDest();
 		int father = arc.getSource();
 		nodes[son] = new Node(son);
 		nodes[father].sons.add(nodes[son]);
-	}	
+	}
 
 	
 	private void createTree(int root, ArrayList<Arc> sortedArcs) {
@@ -290,6 +291,7 @@ public class RootedTree {
 		nodes = new Node[order];
 		nodes[root] = new Node(root);
 
+
 		this.bfsOrder.add(nodes[root]);
 		for (Arc arc : sortedArcs) {
 			createNode(nodes,arc);	
@@ -300,22 +302,22 @@ public class RootedTree {
 		Collections.reverse(inverseBfsOrder);
 		this.root = nodes[root];
 	}
-	
-			
+
+
 	public RootedTree(ArrayList<Edge> edges, int root) {
 		this.order = edges.size() + 1;
 		Graph graph = new Graph(order);
 		for (Edge e : edges) graph.addEdge(e);
 
 		createTree(root, BreadthFirstSearch.generateTree(graph, root));
-		
+
 		rerootTree();
 		computeAllHeights();
 		computeAllSizes();
 		computeAllDepths();
 	}
-	
-		
-	
-	
+
+	public int getOrder() {
+		return order;
+	}
 }
diff --git a/src/Graphics/Labyrinth.java b/src/Graphics/Labyrinth.java
index efa29846d114e1cf641366f91182861d20e0254c..18db9962b26885fd998b84f42bb37454545cd05c 100644
--- a/src/Graphics/Labyrinth.java
+++ b/src/Graphics/Labyrinth.java
@@ -192,8 +192,10 @@ public class Labyrinth extends JPanel {
 			if (grid.isHorizontal(e)) drawHorizontalEdge(g,e);
 			else drawVerticalEdge(g,e);
 		}
-		for (int i = 0; i < grid.graph.order; i++) {
-			drawVertex(g,i);
+		for (int i = 0; i < tree.getOrder(); i++) {
+
+
+				  drawVertex(g,i);
 		}		
 		if (tree != null) drawRoot(g,tree.getRoot());
 
diff --git a/src/Main.java b/src/Main.java
index 741f059fd2ade456ac0b73f5449b990ac11b1628..7ccc68846761d21ba2d1b9a449a108ca0b3df49a 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -2,10 +2,10 @@ import Graph.*;
 import GraphClasses.*;
 import RandomTreeAlgos.BreadthFirstSearch;
 import Graphics.*;
+import TreesAlgo.*;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Random;
+import java.util.*;
 
 import javax.swing.JFrame;
 
@@ -21,33 +21,67 @@ public class Main {
     public static void main(String argv[]) throws InterruptedException {
 
         Graph graph = chooseFromGraphFamily();
-        ArrayList<Edge> randomTree = null;
-
         int noOfSamples = 10;
+
+
+        // Tester l'algorithme Prim
+        System.out.println("-------------------Testing Prim Algorithm------------------------");
+        testAlgorithm(new Prim(graph), noOfSamples);
+
+        // Tester l'algorithme AldousBroder
+        System.out.println("-------------------Testing AldousBroder Algorithm----------------");
+        testAlgorithm(new AldousBroder(graph), noOfSamples);
+
+        // Tester l'algorithme Contraction
+        System.out.println("------------------Testing Contraction Algorithm-----------------");
+        testAlgorithm(new Contraction(graph), noOfSamples);
+
+        // Tester l'algorithme Insertion
+        System.out.println("--------------------Testing Insertion Algorithm-------------------");
+        testAlgorithm(new Insertion(graph), noOfSamples);
+        System.out.println("---------------------Testing Wilson Algorithm----------------------");
+        testAlgorithm(new Wilson(graph), noOfSamples);
+        // Tester l'algorithme RandomSearch
+        System.out.println("---------------------Testing RandomSearch Algorithm----------------");
+        testAlgorithm(new RandomSearch(graph), noOfSamples);
+
+
+
+
+    }
+    private static void testAlgorithm(AbstractArbreCouvrant algorithm, int noOfSamples) {
+        Graph graph = chooseFromGraphFamily();  // Créer un nouveau graphe pour chaque test
+        ArrayList<Edge> randomTree = null;
         Stats stats = new Stats(noOfSamples);
+
         for (int i = 0; i < noOfSamples; i++) {
-            randomTree = genTree(graph);
+            randomTree = genTree(graph, algorithm); // Utilisation de l'algorithme
             stats.update(randomTree);
         }
         stats.print();
-
-        if (grid != null) showGrid(grid, randomTree);
+        if (grid != null) {
+            try {
+                showGrid(grid, randomTree);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
     }
 
     private static Graph chooseFromGraphFamily() {
         // Parametriser ici cette fonction afin de pouvoir choisir
         // quelle classe de graphe utiliser
 
-        grid = new Grid(1920 / 11, 1080 / 11);
+        grid = new Grid(1920 / 20, 1080 / 20);
         Graph graph = grid.graph;
-        //Graph graph = new Complete(400).graph;
+        // Graph graph = new Complete(400).graph;
         //Graph graph = new ErdosRenyi(1_000, 100).graph;
-        //Graph graph = new Lollipop(1_000).graph;
+        // Graph graph = new Lollipop(1_000).graph;
         return graph;
     }
 
-    public static ArrayList<Edge> genTree(Graph graph) {
-        ArrayList<Edge> randomTree;
+    public static ArrayList<Edge> genTree(Graph graph,ArbreCouvrant arbre) {
+     /*  ArrayList<Edge> randomTree;
 
         // TOOO : modifier l'algorithme utilisé ici
         // ou bien parametriser à l'aide de la ligne de commande
@@ -58,7 +92,14 @@ public class Main {
 
         randomTree = new ArrayList<>();
         for (Arc a : randomArcTree) randomTree.add(a.support);
-        return randomTree;
+        return randomTree;*/
+        Set<Edge> arbreCouvrant = arbre.arbreCouvrant(); // Récupérer l'arbre couvrant minimal
+        if (arbreCouvrant == null || arbreCouvrant.isEmpty()) {
+            return new ArrayList<>(); // Retourner une liste vide si l'arbre est invalide
+        }
+
+        return new ArrayList<>(arbreCouvrant);
+
     }
 
 
@@ -139,11 +180,11 @@ public class Main {
 
         // Pour générer un fichier image.
         try {
-            laby.saveImage("resources/random.png");
+            laby.saveImage("resources/search.png");
         } catch (IOException e1) {
             e1.printStackTrace();
         }
 
     }
 
-}
+}
\ No newline at end of file
diff --git a/src/RandomTreeAlgos/BreadthFirstSearch.java b/src/RandomTreeAlgos/BreadthFirstSearch.java
index f357e68d300103370be9327be459548612776519..8d7620bc3501cf0a08d286c4b75bd1da09ddce26 100644
--- a/src/RandomTreeAlgos/BreadthFirstSearch.java
+++ b/src/RandomTreeAlgos/BreadthFirstSearch.java
@@ -32,7 +32,7 @@ public class BreadthFirstSearch {
 		}
 	}
 	
-	private BreadthFirstSearch (Graph graph) {
+	public BreadthFirstSearch (Graph graph) {
 		this.graph = graph;
 		this.frontier = new LinkedList<>();
 		this.tree = new ArrayList<>();
diff --git a/src/Structures/ContractionGraph.java b/src/Structures/ContractionGraph.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c166cb0387cba9a201e6a8fe35c935d9e133485
--- /dev/null
+++ b/src/Structures/ContractionGraph.java
@@ -0,0 +1,89 @@
+package Structures;
+
+import Graph.Edge;
+import Graph.Graph;
+
+import java.util.*;
+
+public class ContractionGraph {
+
+    private List<LinkedList<Integer>> incidence;  // Liste des arêtes incidentes pour chaque sommet
+    private final List<Integer> extrimite1 = new ArrayList<>();
+    private final List<Integer> extrimite2 = new ArrayList<>();
+    private final List<Edge> initialEdges = new ArrayList<>();
+
+    public ContractionGraph(Graph graph) {
+        // Initialisation de la liste incidence avec une nouvelle ArrayList pour chaque sommet
+        this.incidence = new ArrayList<>(graph.order);
+        for (int i = 0; i < graph.order; i++) {
+            incidence.add(new LinkedList<>());  // Initialisation de la liste pour chaque sommet
+        }
+
+        // Parcours tous les sommets du graphe
+        for (int vertex = 0; vertex < graph.order; vertex++) {
+            // Récupère les arêtes sortantes du sommet
+            for (var arc : graph.outEdges(vertex)) {
+                Edge edge = arc.support;
+
+                // Ajout des arêtes aux listes
+                initialEdges.add(edge);
+                extrimite1.add(edge.getSource());
+                extrimite2.add(edge.getDest());
+
+                // Ajout de l'indice de l'arête dans la liste d'incidences des deux sommets
+                incidence.get(edge.getSource()).add(extrimite1.size());
+                incidence.get(edge.getDest()).add(extrimite1.size());
+            }
+        }
+    }
+
+    // Vérifie si une arête est une boucle
+    public boolean boucle(int indexEdge) {
+        return (extrimite1.get(indexEdge).equals(extrimite2.get(indexEdge)));
+    }
+
+    // Contraction de l'arête spécifiée
+    public void contract(int edgeIndex) {
+        if (edgeIndex < 0 || edgeIndex >= extrimite1.size()) {
+            return;
+        }
+
+        int sommet1 = this.extrimite1.get(edgeIndex);
+        int sommet2 = this.extrimite2.get(edgeIndex);
+
+        if (boucle(edgeIndex)) return;
+
+        // Pour chaque arête incidente sur sommet2
+        for (int edge : incidence.get(sommet2)) {
+            if (edge < 0 || edge >= extrimite1.size()) {
+                continue; // Ignore l'arête invalide
+            }
+
+            // Ajouter l'arête incidente à sommet1 si elle n'est pas déjà présente
+            if (extrimite1.get(edge) == sommet1 || extrimite2.get(edge) == sommet1) {
+                this.incidence.get(sommet1).add(edge);
+            }
+
+            // Relier l'arête à sommet1
+            if (extrimite1.get(edge) == sommet2) {
+                this.extrimite1.set(edge, sommet1);
+            }
+            if (extrimite2.get(edge) == sommet2) {
+                this.extrimite2.set(edge, sommet1);
+            }
+        }
+    }
+
+    // Retourne la liste des arêtes initiales
+    public List<Edge> getInitialEdges() {
+        return initialEdges;
+    }
+
+    public List<Integer> getExtrimite1() {
+        return extrimite1;
+    }
+
+    public List<Integer> getExtrimite2() {
+        return extrimite2;
+    }
+}
diff --git a/src/Structures/UnionFind.java b/src/Structures/UnionFind.java
new file mode 100644
index 0000000000000000000000000000000000000000..f62b26050620afd662f5d17b2f79ad5d98eda9da
--- /dev/null
+++ b/src/Structures/UnionFind.java
@@ -0,0 +1,47 @@
+package TreesAlgo;
+
+import java.util.*;
+
+public class UnionFind<T> {
+    private Map<T, T> parent;
+    private Map<T, Integer> rank;
+
+    public UnionFind() {
+        parent = new HashMap<>();
+        rank = new HashMap<>();
+    }
+
+    // Trouver le représentant de l'ensemble, avec compression de chemin
+    public T find(T x) {
+        if (!parent.containsKey(x)) {
+            parent.put(x, x);
+            rank.put(x, 0);
+        }
+        if (!x.equals(parent.get(x))) {
+            parent.put(x, find(parent.get(x))); // Compression de chemin
+        }
+        return parent.get(x);
+    }
+
+    // Fusionner deux ensembles
+    public void union(T x, T y) {
+        T rootX = find(x);
+        T rootY = find(y);
+        if (!rootX.equals(rootY)) {
+            // Union par rang (hauteur)
+            if (rank.get(rootX) > rank.get(rootY)) {
+                parent.put(rootY, rootX);
+            } else if (rank.get(rootX) < rank.get(rootY)) {
+                parent.put(rootX, rootY);
+            } else {
+                parent.put(rootY, rootX);
+                rank.put(rootX, rank.get(rootX) + 1);
+            }
+        }
+    }
+
+    // Vérifie si deux éléments appartiennent au même ensemble
+    public boolean connected(T x, T y) {
+        return find(x).equals(find(y));
+    }
+}
diff --git a/src/TreesAlgo/AbstractArbreCouvrant.java b/src/TreesAlgo/AbstractArbreCouvrant.java
new file mode 100644
index 0000000000000000000000000000000000000000..d0912f20249b1ba4bbf69cf24ba7f2d0ca6e0c32
--- /dev/null
+++ b/src/TreesAlgo/AbstractArbreCouvrant.java
@@ -0,0 +1,20 @@
+package TreesAlgo;
+
+import Graph.Graph;
+import Graph.Edge;
+
+import java.util.HashSet;
+import java.util.Random;
+
+import java.util.Set;
+
+public abstract class AbstractArbreCouvrant implements ArbreCouvrant{
+    protected final Graph graph;
+   protected final Random generator = new Random();
+    protected final Set<Edge> arbre = new HashSet<>();
+
+
+    public AbstractArbreCouvrant(Graph graph) {
+        this.graph = graph;
+    }
+}
diff --git a/src/TreesAlgo/AldousBroder.java b/src/TreesAlgo/AldousBroder.java
new file mode 100644
index 0000000000000000000000000000000000000000..62099a2ab778d7ee1879a0524b68e9c409dabeb5
--- /dev/null
+++ b/src/TreesAlgo/AldousBroder.java
@@ -0,0 +1,45 @@
+package TreesAlgo;
+
+import Graph.Edge;
+import Graph.Graph;
+import Graph.Arc;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class AldousBroder extends AbstractArbreCouvrant {
+
+    private int sommetActuel;                // Sommet courant de la marche
+    private final Set<Integer> sommetVisite; // Ensemble des sommets visités
+
+    public AldousBroder(Graph graph) {
+        super(graph);
+        this.sommetVisite = new HashSet<>();
+        this.sommetActuel = generator.nextInt(graph.order); // Sommet initial aléatoire
+        this.sommetVisite.add(sommetActuel);                // Marquer le sommet initial
+        marcher();                                          // Lancer la marche
+    }
+
+    public void marcher() {
+        while (sommetVisite.size() < graph.order) {
+            // Sélection aléatoire d'un arc sortant
+            Arc arc = graph.outEdges(sommetActuel)[generator.nextInt(graph.outEdges(sommetActuel).length)];
+
+            // Récupérer le sommet voisin via l'arc
+            int voisin = arc.getDest();
+
+            // Si le voisin n'est pas visité, ajouter l'arête dans l'arbre
+            if (sommetVisite.add(voisin)) { // La méthode add() retourne false si le voisin est déjà présent
+                arbre.add(arc.support);    // Ajouter l'arête supportée
+            }
+
+            // Mettre à jour le sommet actuel
+            sommetActuel = voisin;
+        }
+    }
+
+    @Override
+    public Set<Edge> arbreCouvrant() {
+        return arbre; // Retourner l'arbre couvrant construit
+    }
+}
diff --git a/src/TreesAlgo/ArbreCouvrant.java b/src/TreesAlgo/ArbreCouvrant.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a66a1469e7fde71cfe37c1b2332bf80f43db4ed
--- /dev/null
+++ b/src/TreesAlgo/ArbreCouvrant.java
@@ -0,0 +1,10 @@
+package TreesAlgo;
+
+import Graph.Edge;
+
+import java.util.Set;
+
+public interface ArbreCouvrant {
+
+    public Set<Edge> arbreCouvrant();
+}
diff --git a/src/TreesAlgo/Contraction.java b/src/TreesAlgo/Contraction.java
new file mode 100644
index 0000000000000000000000000000000000000000..e13a28742cda100a4fa08322f3603e28c39cdf3a
--- /dev/null
+++ b/src/TreesAlgo/Contraction.java
@@ -0,0 +1,68 @@
+package TreesAlgo;
+
+import Graph.Graph;
+import Graph.Edge;
+import Structures.ContractionGraph;
+
+
+import java.util.*;
+
+public class Contraction extends AbstractArbreCouvrant {
+    private final ContractionGraph contractionGraph;
+    private final TreesAlgo.UnionFind<Integer> unionFind;
+    private final Node[] nodes;  // Tableau pour stocker les informations des sommets
+
+    public Contraction(Graph graph) {
+        super(graph);
+        this.contractionGraph = new ContractionGraph(graph);
+        this.unionFind = new TreesAlgo.UnionFind<>();
+        this.nodes = new Node[graph.getIncidency().size()]; // Initialiser le tableau de noeuds
+        Arrays.fill(this.nodes, new Node()); // Initialiser chaque noeud avec un objet Node
+    }
+
+    @Override
+    public Set<Edge> arbreCouvrant() {
+        List<Integer> edges = new ArrayList<>();
+
+        // Remplir la liste avec des indices d'arêtes
+        for (int i = 0; i < contractionGraph.getExtrimite1().size(); i++) {
+            edges.add(i);
+        }
+
+        // Mélanger les arêtes pour les traiter dans un ordre aléatoire
+        Collections.shuffle(edges);
+        for (int edgeIndex : edges) {
+            if (contractionGraph.boucle(edgeIndex)) {
+                continue;  // Passer les boucles
+            }
+
+            // Récupérer les sommets connectés par l'arête
+            int vertex1 = contractionGraph.getExtrimite1().get(edgeIndex);
+            int vertex2 = contractionGraph.getExtrimite2().get(edgeIndex);
+
+            // Si les sommets sont déjà connectés, ignorer cette arête
+            if (unionFind.find(vertex1) == unionFind.find(vertex2)) {
+                continue;
+            }
+
+            // Ajouter l'arête à l'arbre couvrant
+            arbre.add(contractionGraph.getInitialEdges().get(edgeIndex));
+
+            // Union des sommets pour contracter l'arête
+            unionFind.union(vertex1, vertex2);
+
+            // Contracter l'arête dans le graphe
+            contractionGraph.contract(edgeIndex);
+        }
+
+        return arbre;
+    }
+
+
+
+    // Classe interne pour représenter un sommet avec sa profondeur et hauteur
+    private static class Node {
+        int depth = 0;  // Initialiser à 0 ou à une autre valeur par défaut
+        int height = 0; // Initialiser à 0 ou à une autre valeur par défaut
+    }
+}
diff --git a/src/TreesAlgo/Insertion.java b/src/TreesAlgo/Insertion.java
new file mode 100644
index 0000000000000000000000000000000000000000..5cba34e6cabdda93785478bf358b7888e4f0e4f7
--- /dev/null
+++ b/src/TreesAlgo/Insertion.java
@@ -0,0 +1,43 @@
+package TreesAlgo;
+
+import Graph.Edge;
+import Graph.Graph;
+
+import java.util.*;
+
+public class Insertion  extends AbstractArbreCouvrant {
+
+    private List<Edge> arretesRestant = new ArrayList<>();
+    private final TreesAlgo.UnionFind<Integer> forest;
+
+    public Insertion(Graph graph) {
+        super(graph);
+        this.forest = new TreesAlgo.UnionFind<>();
+        // Initialiser la liste d'arêtes restantes
+        for (LinkedList<Edge> edgeList : graph.getIncidency()) {
+            arretesRestant.addAll(edgeList);
+        }
+    }
+
+    @Override
+    public Set<Edge> arbreCouvrant() {
+        // Mélanger les arêtes pour assurer un tirage aléatoire
+        Collections.shuffle(arretesRestant, generator);
+
+        while (arbre.size() < graph.order - 1) {
+            // Tirer une arête au hasard
+            Edge e = arretesRestant.remove(0);
+            int u = e.getSource();
+            int v = e.getDest();
+
+            // Vérifier si l'ajout de l'arête forme un cycle
+            if (!forest.connected(u, v)) {
+                // Si ce n'est pas un cycle, ajouter l'arête à l'arbre couvrant
+                arbre.add(e);
+                forest.union(u, v); // Fusionner les ensembles contenant u et v
+            }
+        }
+
+        return arbre;
+    }
+}
diff --git a/src/TreesAlgo/Prim.java b/src/TreesAlgo/Prim.java
new file mode 100644
index 0000000000000000000000000000000000000000..539aaeca28fb14a7c4bfe716e633852a6bf20d26
--- /dev/null
+++ b/src/TreesAlgo/Prim.java
@@ -0,0 +1,79 @@
+package TreesAlgo;
+
+import Graph.Edge;
+import Graph.Graph;
+import Graph.Arc;
+
+import java.util.*;
+
+public class Prim extends AbstractArbreCouvrant{
+
+
+    private final Map<Edge,Double> poids=new HashMap<>();
+
+
+    private final PriorityQueue<Edge> queue= new PriorityQueue<>(Comparator.comparingDouble(poids::get));
+
+
+
+    public Prim(Graph graph) {
+       super(graph);
+
+     genererPoidsAleatoires();
+
+    }
+    private void genererPoidsAleatoires() {
+        int nbEdge = graph.getEdgeCardinality();
+        int borneSup = (nbEdge > 500) ? Integer.MAX_VALUE : nbEdge * nbEdge * nbEdge;
+
+        // Étape 1 : Attribuer un poids aléatoire [0, 1] à chaque arête
+        for (int i = 0; i < graph.order; i++) {
+            if (graph.isVertex(i)) {
+                for (Edge edge : graph.getIncidency().get(i)) {
+                    if (!poids.containsKey(edge)) { // Assurez-vous de ne pas ajouter deux fois une arête
+                        // Utilisez nextInt() pour obtenir un entier entre 0 et borneSup,
+                        // puis divisez par borneSup pour normaliser le poids entre 0 et 1.
+                        double weight = generator.nextInt(borneSup) / (double) borneSup;
+                        poids.put(edge, weight);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public Set<Edge> arbreCouvrant() {
+        // Étape 1 : Choisir un sommet de départ
+        int startVertex = 0; // On peut commencer avec n'importe quel sommet
+        Set<Integer> visited = new HashSet<>();
+        visited.add(startVertex);
+
+        // Étape 2 : Ajouter toutes les arêtes sortantes du sommet choisi dans la priorité
+        for (Edge edge : graph.getIncidency().get(startVertex)) {
+            queue.add(edge);
+        }
+
+        // Étape 3 : Boucle principale de Prim
+        while (!queue.isEmpty()) {
+            Edge edge = queue.poll(); // Obtenir l'arête de poids minimum
+            int dest = edge.getDest();
+
+            // Si l'une des extrémités de l'arête n'est pas encore visitée, l'ajouter à l'arbre
+            if (!visited.contains(dest)) {
+                arbre.add(edge);
+                visited.add(dest);
+
+                // Ajouter toutes les arêtes sortantes de ce sommet dans la queue
+                for (Edge e : graph.getIncidency().get(dest)) {
+                    if (!visited.contains(e.getDest())) {
+                        queue.add(e);
+                    }
+                }
+            }
+        }
+
+        return arbre;
+    }
+
+
+}
diff --git a/src/TreesAlgo/RandomSearch.java b/src/TreesAlgo/RandomSearch.java
new file mode 100644
index 0000000000000000000000000000000000000000..5bc258059a5fc423d7c77d67c83ec71946b267fd
--- /dev/null
+++ b/src/TreesAlgo/RandomSearch.java
@@ -0,0 +1,57 @@
+package TreesAlgo;
+
+import Graph.Arc;
+import Graph.Graph;
+import Graph.Edge;
+
+import java.util.*;
+
+public class RandomSearch extends AbstractArbreCouvrant {
+
+    private Set<Integer> visited= new HashSet<>();
+
+    public RandomSearch(Graph graph) {
+        super(graph);
+    }
+
+
+    @Override
+    public Set<Edge> arbreCouvrant() {
+        // Tirer un sommet aléatoire parmi les sommets existants du graphe
+        int root = generator.nextInt(graph.order);  // Sommet aléatoire entre 0 et graph.order - 1
+        visited.add(root);
+
+        // Liste des arcs à explorer, initialement vide
+        List<Arc> frontier = new ArrayList<>();
+
+        // Ajouter les arcs sortants du sommet de départ à la frontière
+        for (Arc arc : graph.outEdges(root)) {
+            frontier.add(arc);
+        }
+
+        // Tant qu'il reste des arcs à explorer
+        while (!frontier.isEmpty()) {
+            // Choisir un arc au hasard parmi ceux de la frontière
+            Collections.shuffle(frontier, generator);
+            Arc arc = frontier.remove(0);  // Retirer l'arc choisi
+
+            int dest = arc.getDest();
+
+            // Si le sommet destination n'a pas été visité, on l'explore
+            if (!visited.contains(dest)) {
+                visited.add(dest);
+                // Ajouter l'arc (sous forme d'Edge) à l'arbre couvrant
+                arbre.add(arc.support);  // Accéder à l'Edge via le champ 'support' de l'Arc
+
+                // Ajouter tous les arcs sortants du sommet destination à la frontière
+                for (Arc newArc : graph.outEdges(dest)) {
+                    if (!visited.contains(newArc.getDest())) {
+                        frontier.add(newArc);  // Ajouter les arcs sortants à la frontière
+                    }
+                }
+            }
+        }
+
+        return arbre;  // Retourner le Set<Edge>
+    }
+}
\ No newline at end of file
diff --git a/src/TreesAlgo/SuppressionCycle.java b/src/TreesAlgo/SuppressionCycle.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab955caee5d409eb687977ec4ebcc71976ba7dd9
--- /dev/null
+++ b/src/TreesAlgo/SuppressionCycle.java
@@ -0,0 +1,91 @@
+package TreesAlgo;
+
+import Graph.Edge;
+import Graph.Graph;
+
+import java.util.*;
+
+public class SuppressionCycle extends AbstractArbreCouvrant {
+
+    private final Map<Integer, Integer> parent = new HashMap<>();  // Parent de chaque sommet
+    private final Set<Integer> visited = new HashSet<>();         // Sommets visités
+    private final Set<Integer> inCycle = new HashSet<>();         // Sommets dans un cycle
+    private final List<Edge> edgesInCycle = new ArrayList<>();    // Arêtes à supprimer dans un cycle
+    private final int root;                                         // Racine de l'arbre
+
+    public SuppressionCycle(Graph graph) {
+        super(graph);
+        this.root = 0;  // Sommet racine (à ajuster si nécessaire)
+        construireArbre();
+    }
+
+    private void construireArbre() {
+        // Lancer le DFS à partir du sommet racine
+        dfsIteratif(root);
+        supprimerCycles();
+    }
+
+    private void dfsIteratif(int sommet) {
+        Stack<Integer> stack = new Stack<>();
+        Stack<Edge> edgeStack = new Stack<>(); // Stack pour garder la trace des arêtes
+        stack.push(sommet);
+        visited.add(sommet);
+
+        while (!stack.isEmpty()) {
+            int currSommet = stack.peek();
+            boolean addedNew = false;
+
+            // Parcourir les voisins à travers les arêtes incidentes
+            for (Edge edge : graph.getIncidency().get(currSommet)) {
+                int voisin = edge.oppositeExtremity(currSommet);
+
+                if (!visited.contains(voisin)) {
+                    // Ajouter l'arête dans l'arbre couvrant
+                    arbre.add(edge);
+                    parent.put(voisin, currSommet);  // Mettre à jour le parent
+                    visited.add(voisin);
+                    edgeStack.push(edge);  // Empiler l'arête
+                    stack.push(voisin);  // Empiler le voisin
+                    addedNew = true;
+                    break;  // Sortir de la boucle dès qu'un voisin est ajouté
+                } else if (inCycle.contains(voisin)) {
+                    // Si on revient à un sommet déjà dans un cycle, un cycle est détecté
+                    System.out.println("Cycle détecté : " + edge);
+                    edgesInCycle.add(edge);
+                    inCycle.add(voisin);  // Ajouter le sommet au cycle
+                    return;  // Fin de la détection de cycle
+                } else {
+                    // Si l'arête forme un cycle avec un sommet déjà visité, on ajoute à la liste des arêtes
+                    edgesInCycle.add(edge);
+                }
+            }
+
+            // Si aucun voisin n'a été ajouté, on retire le sommet de la pile de récursion
+            if (!addedNew) {
+                stack.pop();
+                if (!edgeStack.isEmpty()) {
+                    edgeStack.pop(); // Retirer l'arête associée
+                }
+            }
+        }
+    }
+
+    private void supprimerCycles() {
+        // Supprimer les cycles détectés
+        Set<Edge> edgesToRemove = new HashSet<>();
+        for (Edge edge : edgesInCycle) {
+            if (arbre.contains(edge)) {
+                edgesToRemove.add(edge);
+                System.out.println("Suppression de l'arête : " + edge);
+            }
+        }
+
+        // Supprimer les arêtes du cycle
+        arbre.removeAll(edgesToRemove);
+    }
+
+    @Override
+    public Set<Edge> arbreCouvrant() {
+        return arbre;  // Retourner l'arbre couvrant
+    }
+}
diff --git a/src/TreesAlgo/Wilson.java b/src/TreesAlgo/Wilson.java
new file mode 100644
index 0000000000000000000000000000000000000000..a87fcbb89f12d9378fd4a196a5316e456ac9021c
--- /dev/null
+++ b/src/TreesAlgo/Wilson.java
@@ -0,0 +1,55 @@
+package TreesAlgo;
+
+import Graph.Edge;
+import Graph.Graph;
+
+import java.util.*;
+import java.util.stream.IntStream;
+
+public class Wilson extends AbstractArbreCouvrant {
+
+    private final Set<Integer> sommetVisite = new HashSet<>();
+    private final Map<Integer, Edge> outArc = new HashMap<>();
+
+    public Wilson(Graph graph) {
+        super(graph);
+        // Sort vertices in descending order of degree and choose a vertex at each iteration
+        IntStream.range(0, graph.order)
+                .boxed()
+                .sorted(Comparator.comparingInt(graph::degreSommet).reversed())
+                .forEach(
+                        source -> {
+                            if (sommetVisite.isEmpty()) {
+                                sommetVisite.add(source); // Add the first vertex
+                            } else {
+                                walk(source); // Perform a random walk starting from other vertices
+                            }
+                        }
+                );
+    }
+
+    private void walk(int source) {
+        int currentVertex = source;
+
+        // Perform a random walk until reaching an already visited vertex
+        while (!sommetVisite.contains(currentVertex)) {
+            int rand = generator.nextInt(graph.getIncidency().get(currentVertex).size());
+            Edge edge = graph.getIncidency().get(currentVertex).get(rand); // Get a random edge
+            outArc.put(currentVertex, edge); // Record the edge to retrace the path later
+            currentVertex = edge.oppositeExtremity(currentVertex); // Move to the other endpoint of the edge
+        }
+
+        currentVertex = source;
+        // Retrace the path and mark vertices as visited
+        while (!sommetVisite.contains(currentVertex)) {
+            sommetVisite.add(currentVertex); // Add the vertex to the spanning tree
+            arbre.add(outArc.get(currentVertex)); // Add the edge to the result
+            currentVertex = outArc.get(currentVertex).oppositeExtremity(currentVertex); // Move to the other endpoint
+        }
+    }
+
+    @Override
+    public Set<Edge> arbreCouvrant() {
+        return arbre; // Return the spanning tree
+    }
+}