#include <stdlib.h>
#include <stdio.h>
#include <time.h>




//--------------------------------------Structures Karger---------------------------------------------------






/* Définit une structure pour représenter une arête dans un graphe non pondéré. */
struct Arete {
    int source, destination; // Contient les identifiants des sommets source et destination de l'arête.
};

/* Définit une structure pour représenter un graphe comme une collection d'arêtes. */
struct Graphe {
    int nbSommets, nbAretes; // Stocke le nombre de sommets et d'arêtes dans le graphe.
    struct Arete* arete; // Pointeur vers un tableau d'arêtes.
};

/* Structure pour gérer les sous-ensembles dans l'algorithme union-trouver. */
struct SousEnsemble {
    int parent; // Identifiant du parent dans l'ensemble.
    int rang; // Profondeur de l'arbre de l'ensemble.
};


//-----------------------------Déclarattion fonctions globales---------------------------------------


void Cree_graphe_a_partir_de_fichier(struct Graphe* G, const char* nomFichierGraphe);

//---------------------------Déclaration des fonctions Karger -------------------------------------------



struct Graphe* creerGraphe(int nbSommets, int nbAretes);
int trouverRacine(struct SousEnsemble sousEnsembles[], int i);
void Union(struct SousEnsemble sousEnsembles[], int x, int y);
int coupeMinKarger(struct Graphe* graphe) ;

//-------------------------------Fonctions----------------------------------------------------------


//Fonction pour créer un nouveau graphe avec un nombre spécifié de sommets et d'arêtes


struct Graphe* creerGraphe(int nbSommets, int nbAretes)
{
    // Alloue dynamiquement de la mémoire pour une nouvelle structure Graphe
    struct Graphe* graphe = (struct Graphe*)malloc(sizeof(struct Graphe));
    
  
    graphe->nbSommets = nbSommets;  // Initialise le nombre de sommets du graphe avec la valeur fournie
   
    graphe->nbAretes = nbAretes; // Initialise le nombre d'arêtes du graphe avec la valeur fournie
   
    graphe->arete = (struct Arete*)malloc(nbAretes * sizeof(struct Arete)); // Alloue dynamiquement de la mémoire pour un tableau d'arêtes basé sur le nombre d'arêtes spécifié
   
    return graphe; // Retourne un pointeur vers le graphe nouvellement créé
}








// Fonction qui trouve la racine d'un ensemble noeud 


int trouverRacine(struct SousEnsemble sousEnsembles[], int i) // Définit la fonction trouverRacine, qui trouve la racine de l'ensemble contenant i.

{ 
    if (sousEnsembles[i].parent != i) // Si i n'est pas son propre parent, i n'est pas la racine.
    
    { 
        
        sousEnsembles[i].parent = trouverRacine(sousEnsembles, sousEnsembles[i].parent); // Recherche récursivement la racine de i et applique la compression de chemin.
    }
    return sousEnsembles[i].parent; // Retourne la racine de l'ensemble contenant i.
}



// Fonction qui fait l'union de deux sous ensembles x et y 


void Union(struct SousEnsemble sousEnsembles[], int x, int y)

{
    // Trouve la racine de l'ensemble contenant l'élément x
    int racineX = trouverRacine(sousEnsembles, x);
    // Trouve la racine de l'ensemble contenant l'élément y
    int racineY = trouverRacine(sousEnsembles, y);

    // Compare les rangs des racines des deux éléments
    if (sousEnsembles[racineX].rang < sousEnsembles[racineY].rang) // Si le rang de racineX est inférieur à celui de racineY, fait de racineY le parent de racineX
    {
       
        sousEnsembles[racineX].parent = racineY;
    } else if (sousEnsembles[racineX].rang > sousEnsembles[racineY].rang) // Si le rang de racineX est supérieur à celui de racineY, fait de racineX le parent de racineY
    {
        
        sousEnsembles[racineY].parent = racineX;
    } else  // Si les rangs sont égaux, choisit racineX comme parent de racineY
    {
       
        sousEnsembles[racineY].parent = racineX;
        // Et augmente le rang de racineX puisqu'il a maintenant un sous-arbre supplémentaire
        sousEnsembles[racineX].rang++;
    }
}







//Fonction pour  l'algorithme de Karger.


int coupeMinKarger(struct Graphe* graphe) 

{
   
    int nbSommets = graphe->nbSommets, nbAretes = graphe->nbAretes; // Récupère le nombre de sommets et d'arêtes du graphe donné.
    
    struct Arete* arete = graphe->arete;
   
    struct SousEnsemble* sousEnsembles = (struct SousEnsemble*)malloc(nbSommets * sizeof(struct SousEnsemble)); // Alloue la mémoire pour les sous-ensembles correspondant à chaque sommet.
    
   
    for (int v = 0; v < nbSommets; ++v) // Initialise chaque sous-ensemble pour qu'il soit auto-referent avec un rang initial de 0.
        
    {
        sousEnsembles[v].parent = v;
        sousEnsembles[v].rang = 0;
    }
   
    int nbSommetsRestants = nbSommets; // Initialise le nombre de sommets restants à être contractés.
    
    while (nbSommetsRestants > 2) // Continue de contracter les arêtes tant qu'il reste plus de deux sommets.
    
    {
       
        int i = rand() % nbAretes; // Sélectionne une arête aléatoirement.
       
        int sousEnsemble1 = trouverRacine(sousEnsembles, arete[i].source); // Trouve les racines des sous-ensembles des sommets de l'arête sélectionnée.
        int sousEnsemble2 = trouverRacine(sousEnsembles, arete[i].destination);
      
        if (sousEnsemble1 != sousEnsemble2)   // Contracte l'arête si elle connecte deux sous-ensembles différents.
        {
          
            printf("Contration de l'arête %d-%d\n", arete[i].source, arete[i].destination);  // Affiche l'arête contractée pour information.
            
            nbSommetsRestants--;// Réduit le compteur de sommets restants après la contraction.
           
            Union(sousEnsembles, sousEnsemble1, sousEnsemble2); // Fusionne les deux sous-ensembles en un seul.
        }
    }
    // Compte le nombre total d'arêtes coupées.
    int aretesCoupees = 0;
    for (int i = 0; i < nbAretes; i++) {
        // Vérifie si l'arête actuelle est une coupe entre deux sous-ensembles.
       int sousEnsemble1 = trouverRacine(sousEnsembles, arete[i].source); // Trouve et stocke la racine (ou le représentant) du sous-ensemble contenant le sommet source de l'arête courante.
       int sousEnsemble2 = trouverRacine(sousEnsembles, arete[i].destination); // Trouve et stocke la racine (ou le représentant) du sous-ensemble contenant le sommet destination de l'arête courante.

        if (sousEnsemble1 != sousEnsemble2)
        {
            // Incrémente le compteur d'arêtes coupées.
            aretesCoupees++;
        }
    }
    // Libère la mémoire allouée aux sous-ensembles.
    free(sousEnsembles);
    
    return aretesCoupees; // Retourne le nombre d'arêtes coupées, indiquant la taille de la coupe minimale.
}






int main() 
{

     int nbSommets = 6;  // Nombre de sommets dans le graphe
    int nbAretes = 7;   // Nombre d'arêtes dans le graphe
    struct Graphe* graphe = creerGraphe(nbSommets, nbAretes);

    // Ajout des arêtes. Exemple : (0, 2) représente une arête entre le sommet A et C
    graphe->arete[0].source = 0; graphe->arete[0].destination = 2;
    graphe->arete[1].source = 0; graphe->arete[1].destination = 1;
    graphe->arete[2].source = 1; graphe->arete[2].destination = 2;
    graphe->arete[3].source = 1; graphe->arete[3].destination = 3;
    graphe->arete[4].source = 3; graphe->arete[4].destination = 4;
    graphe->arete[5].source = 4; graphe->arete[5].destination = 5;
    graphe->arete[6].source = 5; graphe->arete[6].destination = 3;

    srand(time(NULL));
    printf("\nLa coupe minimale trouvée par l'algorithme aléatoire de Karger est %d\n", coupeMinKarger(graphe));

    free(graphe->arete);
    free(graphe);

   
    return 0;
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: