Points d'attache



next up previous contents index
Next: Programmes en C Up: Composantes fortement connexes Previous: Utilisation de l'arborescence

Points d'attache

    Une notion utile pour le calcul des composantes fortement connexe est la notion de point d'attache dont la définition est donnée ci-dessous. Rappelons que l'on suppose les sommets numérotés dans l'ordre où on les rencontre par la procédure de Trémaux.

On remarquera qu'un chemin qui conduit d'un sommet à son point d'attache est ou bien vide (le point d'attache est alors lui même), ou bien contient une suite d'arcs de suivis par un arc de retour ou un arc transverse. En effet, une succession d'arcs de partant de conduit à un sommet de numéro plus grand que , d'autre part les arcs de descente ne sont pas utiles dans la recherche du point d'attache, ils peuvent être remplacés par des chemins formés d'arcs de .

  
Figure: Les points d'attaches des sommets d'un graphe

Dans la figure gif, on a calculé les points d'attaches des sommets d'un graphe, ceux-ci ont été numérotés dans l'ordre où on les rencontre dans l'algorithme de Trémaux; le point d'attache est indiqué en petit caractère à coté du sommet en question.

  Le calcul des points d'attache se fait à l'aide d'un algorithme récursif qui est basé sur la proposition suivante, dont la preuve est immédiate:

L'algorithme est ainsi une adaptation de l'algorithme de Trémaux, il calcule at[u] en utilisant la valeur des at[v] pour tous les successeurs v de u.

 

 
var
    at: SomVect;
    succ: GrapheSuc;

function PointAttache (u: Sommet): Sommet;
    var
        k: integer;
        v, w, mi: Sommet;
    begin
    k := 1;
    v := succ[u, k];
    mi := u;
    at[u] := u;
    while (v <> Omega) do
        begin
        if (at[v] = Omega) then
            w := PointAttache(v)
        else
            w := v;
        mi := Min(mi, w);
        k := k + 1;
        v := succ[u, k];
        end;
    at[u] := mi;
    PointAttache := mi
    end;

for i := 1 to n do
    at[i] := Omega;
at[x] := PointAttache(x);

Le calcul des composantes fortement connexes à l'aide des est une conséquence du théorème suivant:

 

Preuve Montrons d'abord que tout sommet de appartient à . Soit un sommet de , il est extrémité d'un chemin d'origine , prouvons que est aussi extrémité d'un chemin d'origine . Si tel n'est pas le cas, on peut supposer que est le plus petit sommet de à partir duquel on ne peut atteindre , soit le chemin joignant à , le chemin obtenu en concaténant à un chemin de d'origine et d'extrémité contient au plus un arc de retour ou transverse ainsi:

Comme est préfixe, appartient à et d'après l'hypothèse de minimalité il existe un chemin d'origine et d'extrémité qui concaténé à fournit la contradiction cherchée.

Il reste à montrer que tout sommet de appartient aussi à . Un tel sommet est extrémité d'un chemin d'origine , nous allons voir que tout arc dont l'origine est dans a aussi son extrémité dans , ainsi tous les sommets de sont dans et en particulier . Soit un arc tel que , si , est un descendant de il appartient donc à ; si alors le chemin menant de à en passant par contient exactement un arc de retour ou transverse, ainsi :

et la préfixité de implique .

Remarques

  1. Il existe toujours un sommet du graphe satisfaisant les conditions de la proposition ci-dessus. En effet, si est la racine de on a . Si satisfait (ii), alors l'ensemble en entier constitue une composante fortement connexe. Sinon il existe un descendant de tel que . En répétant cet argument plusieurs fois et puisque le graphe est fini, on finit par obtenir un sommet satisfaisant les deux conditions.

  2. La recherche des composantes fortement connexes est alors effectuée par la détermination d'un sommet tel que , obtention d'une composante égale à , suppression de tous les sommets de et itération des opérations précédentes jusqu'à obtenir tout le graphe.

  3. Sur la figure gif, on peut se rendre compte du procédé de calcul. Il y a composantes fortement connexes, les sommets satisfaisant sont au nombre de , il s'agit de . La première composante trouvée se compose du sommet uniquement, il est supprimé et le sommet devient alors tel que . Tous ses descendants forment une composante fortement connexe . Après leur suppression, le sommet satisfait et il n'a plus de descendant satisfaisant la même relation. On trouve ainsi une nouvelle composante . Une fois celle-ci supprimée est le seul sommet qui satisfait la relation d'où la composante . Dans ce cas particulier du sommet , on peut atteindre tous les sommets du graphe et le calcul s'arrête donc là; en général il faut reconstruire une arborescence de Trémaux à partir d'un sommet non encore atteint.

L'algorithme ci-dessous, en Pascal, calcule en même temps pour tous les descendants de et obtient successivement toutes les composantes fortement connexes de . Il utilise le fait, techniquement long à prouver mais guère difficile que la suppression des descendants de lorsque ne modifie pas les calculs des en cours. La programmation donnée ici suppose que les sommets ont déjà été numérotés par l'algorithme de Trémaux à partir de :

 

var val:array[sommet] of integer;
    succ: GrapheSuc;
    n:integer;
 
procedure Supprimer (u: Sommet;  nu: integer; 
                     var numComp: SomVect);
     (*La suppression d'un sommet s'effectue *)
     (*-*)
    var
       v: Sommet;
       k: integer;
    begin
    numComp[u] := nu;
    k := 1;
    v := succ[u, k];
    while v <> Omega do
        begin
        if (v > u) and (numComp[v] = 0) then
            Supprimer(v, nu, numComp);
        k := k + 1;
        v := succ[u, k];
        end;
    end;

procedure PointAttache1 (u: Sommet;  var nu: integer; 
                         var at, numComp: Somvect);
    var
        k: integer;
        v, w: Sommet;
    begin
    at[u] := u;      (*Recherche du point d'attache de u*)
    k := 1;          (*-*)
    v := succ[u, k];
    while (v <> Omega) do
        begin
        if (at[v] = Omega) then
            begin
            PointAttache1(v, nu, at, numComp);
            at[u] := Min(at[u], at[v]) (*- *)
            end
        else if numComp[u] = 0 then
            at[u] := Min(at[u], v);
        k := k + 1;
        v := succ[u, k];
        end;
      (* - *) 
      (* - *)
        if u = at[u] then
            begin
            nu := nu + 1;
            Supprimer(u, nu, numComp);
            end;
    end;


procedure CompCon (var numComp: SomVect);
    var
        k, mi, num: integer;
        at: somvect;
        u, v, w: Sommet;
    begin
    for u := 1 to n do
        begin
        numComp[u] := 0;
        at[u] := Omega;
        end;
    u := 1;
    num := 0;
    for u := 1 to n do
        if ((numComp[u]) = 0 and (at[u] = Omega)) then
            PointAttache1(u, num, at, numComp)
    end;



next up previous contents index
Next: Programmes en C Up: Composantes fortement connexes Previous: Utilisation de l'arborescence