Théorie des graphes et algorithmes

Algorithme de Prim pour trouver un arbre de recouvrement minimal

FondamentalThéorème sur lequel repose l'algorithme de Prim

On considère un graphe non orienté valué G=(X, E, V) ainsi que l'ensemble des arbres de recouvrement notés (X, F, V) de ce graphe.

On note (X, F, V)→(X',F',V) l'ensemble des arbres de recouvrement du graphe G=(X, E, V) qui contiennent l'arbre A=(X', F', V) du sous graphe (X', E', V) de (X, E, V)

(X' est strictement contenu dans X et F' est strictement contenu dans F).

Parmi les arbres de recouvrement minimaux du graphe (X, E, V) pour lesquels le sous-arbre A=(X', F', V) est imposé, il en existe au moins un qui contient l'arête de valeur minimale ayant une de ses extrémités dans X' et son autre extrémité dans X-X'.

Éléments de démonstration du théorème

Comme pour l'algorithme de Kruskal, la démonstration se fait par l'absurde.

Considérons un graphe G (dont les points sont dans X) et considérons un sous-graphe A de ce graphe (dont les points sont X') qui soit un arbre.

Soit F un arbre de recouvrement de G qui contient l'arbre A, mais qui ne contient aucune des arêtes de coût minimal dont une de ses extrémités est dans X et l'autre extrémité dans X'.

Soit b une des arêtes de coût minimal entre X et X'. Si on l'ajoute à l'arbre F, on crée obligatoirement un cycle. Ce cycle contient exactement deux arêtes ayant une extrémité dans X et une extrémité dans X', b et une autre arête c. Si on enlève c, on casse ce cycle. On a donc un graphe sans cycle de n-1 arêtes, c'est donc un arbre et comme le coût de b est strictement plus petit que celui de c, on a construit un arbre de recouvrement de poids strictement inférieur à celui de l'arbre minimal considéré qui n'était donc pas minimal.

Utilisation du théorème pour construire l'algorithme de Prim

On choisit arbitrairement n'importe quel point pour démarrer la construction de l'arbre, par exemple le point numéroté 1.

L'arbre A est alors constitué de ({1},Ø) c'est à dire le point 1 et pas d'arêtes.

On cherche dans le graphe G un des points dont la distance à 1 est la plus courte. Soit x ce point.

On met alors dans l'arbre le point x et l'arête joignant 1 à x. A=({1,x}, {{1,x}}).

Pour tous les points y autres que 1 et x (y n'est pas dans A), on calcule la distance la plus courte de y à A, c'est à dire la distance la plus courte entre y et 1 ou entre y et x.

Parmi ces points y, on retient un de ceux dont la distance de y à A est la plus courte et l'arête {y,z} qui assure cette distance minimale (avec z dans A).

On ajoute à A le point y dans l'ensemble des points et l'arête {y,z} dans l'ensemble des arêtes.

On recommence à chercher un nouveau point y qui n'est pas dans l'arbre et dont la distance à l'arbre est la plus courte et on l'ajoute à l'arbre ainsi que l'arête la plus courte qui relie y à l'arbre.

On itère cette opération jusqu'à ce que tous les points de X soient dans A. On a alors n points dans A et n-1 arêtes.

Les structures de données utilisées dans l'algorithme de Prim

On utilise deux tableaux de n éléments, où n est le nombre de points.

L'élément DISTANCE(i) contient -1 si i fait déjà partie de l'arbre en cours de construction A (i est dans X').

Dans l'animation, nous avons barré les cases correspondantes de manière à mieux voir les points non barrés de X-X'.

L'élément DISTANCE(i) contient +∞ s'il n'y a pas d'arête dans G qui relie le point i à l'arbre en cours de construction A.

L'élément DISTANCE(i) contient la longueur d'une des plus courtes arêtes de G qui relie le point i à un des points de X'.

L'élément PROX(i) contient - 1 si i fait déjà partie de l'arbre en cours de construction A (i est dans X').

Dans l'animation, nous avons barré les cases correspondantes de manière à mieux voir les points non barrés de X-X'.

L'élément PROX(i) contient 0 si i n'est pas dans X' et s'il n'y a pas d'arête dans G qui relie le point i à l'arbre en cours de construction A.

L'élément PROX(i) contient j un des points les plus proches de i dans l'arborescence en cours de construction A lorsqu'il existe au moins une arête entre i et l'arbre A.

R est l'ensemble des points de X-X'. Card(R) désigne le nombre d'éléments dans R.

F est l'ensemble des arêtes de l'arbre en cours de construction.

Description de l'algorithme de Prim

// Initialisation :

Pour tout i faire

    DISTANCE(i)=+∞;

    PROX(i)=-1

Finpourtout i;

// Le point 1 est choisi arbitrairement comme point de départ de l'arbre A.

// On suppose que V(i,j)= +∞ lorsque l'arête {i,j} n'existe pas.

Pour tout j faire

    DISTANCE(j)=V(1,j) ;

    si DISTANCE(j) == +∞

        alors PROX(i)=0;

        sinon PROX(i)=1;

    finsi;

Finpourtout

DISTANCE(1)=-1 ;

PROX(1)=-1 ;

R=X-{1} ;

F=Ø ;

erreur = faux ;

// Itérations :

Tantque card(R) > 0 et erreur == faux faire

  mini=+∞ ;

  proche=0 ;

  Pour tout j de R faire

      si DISTANCE(j) < mini alors

          mini=DISTANCE(j);

          proche=j ;

      finsi;

  Finpourtout j ;

  si proche == 0 alors

        erreur = vrai;

  sinon

        R=R-{proche} ;

        F=F U {{proche,PROX(proche)} ;

        DISTANCE(proche)=-1 ;

        PROX(proche)=-1 ;

        // mise à jour de DISTANCE et de PROX

        Pour tout j de R faire

            si DISTANCE(j)>V(j,proche) alors

                DISTANCE(j)=V(j,proche);

                PROX(j)=proche fsi ;

            finsi;

         Finpourtout j ;

  finsi

Fintantque ;

// Fin de l'algorithme

si erreur == faux alors

      F contient les arêtes d'un arbre de recouvrement minimal

sinon

     le graphe G n'était pas connexe

finsi;

Animation permettant de dérouler en pas à pas l'algorithme de Prim sur des exemples

Cliquez sur Anim pour démarrer l'animation. Vous pouvez ensuite sélectionner le graphe sur lequel vous souhaitez dérouler l'algorithme en pas à pas. Il est à noter que l'affichage de l'animation commence à la fin de la phase d'initialisation.

Complexité de l'algorithme de Prim

Il y a exactement n itérations principales et une boucle d'au plus n itérations à l'intérieur, c'est donc un algorithme polynomial en O(n2).

Remarque

L'algorithme de Kruskal est donc intéressant quand il y a peu d'arêtes dans le graphe G alors que l'algorithme de Prim ne dépend pas du nombre d'arêtes et a une complexité constante lorsque le nombre de points est fixé.

PrécédentPrécédentSuivantSuivant
AccueilAccueilImprimerImprimerRéalisé avec Scenari (nouvelle fenêtre)