Adloun

Corrigé X-ENS 2025 Informatique C MPI — Partie I (2) (Q11 à Q21) : Bourgeons, forêts et algorithme d'Edmonds

Sujet officiel du concours X-ENS, session 2025, épreuve Informatique C MPI. Corrigé rédigé par Ibrahim Alame.

Sujet officiel (PDF, site du concours)

Énoncé

Notations de la première moitié. Un bourgeon est un cycle de longueur ayant arêtes dans ; sa base ( ci-dessous, arêtes de épaisses) est le sommet dont les deux arêtes du cycle sont hors de . On le code par la liste de ses sommets, sans répétition.

Pour et , a pour sommets , pour arêtes celles de hors de et les , voisin d'un sommet de . renomme lst rnm w remplace dans lst les éléments de rnm par w, sans doublons. contient les disjointes de et les , , , . Admis : a un chemin d'augmentation dans si et seulement si en a un dans .


type arbre = N of int * foret
and foret = arbre list

Recherche. (1) : une racine (profondeur ) par sommet non couvert ; (2) ; (3) tant qu'un est à profondeur paire, l'ajouter à et, pour chaque voisin : (a) si , ajouter à et ; (b) si , sont à profondeur paire : (i) arbres distincts : renvoyer les sommets de à puis de à ; (ii) même arbre : contracter le bourgeon et chercher dans . Admis : l'algorithme réussit si et seulement s'il existe un chemin d'augmentation. Fournies : frais (entier neuf), prochain (sommet de profondeur paire non traité), apparie, gonfle (relève un chemin de dans ). Figure 1 :


let rec recherche graphe couplage =
    let nc = del (keys graphe) (couverts couplage) in
    let foret = ref (List.map (fun x -> N(x,[])) nc) in
    let rec aux_voisins u liste_voisins =
        let cu = Option.get (find !foret u) in
        match liste_voisins with
        | [] -> None
        | v :: tl ->
                  match find !foret v with
                  | None -> let z = apparie couplage v in
                            foret := extend (extend !foret u v) v z;
                            aux_voisins u tl
                  | Some cv when (List.length cv) mod 2 = 0
                  (* nombre de sommets pair = profondeur impaire *)
                         -> ...
                  | Some cv when (List.hd cu) <> (List.hd cv)
                         -> ...
                            ...
                  | Some cv
                         -> let bourgeon = extrait cu cv in
                            let nv = frais (keys graphe) in
                            let ng = contracteG graphe bourgeon nv in
                            let nc = contracteC couplage bourgeon nv in
                            ...
                            ...
                            ...
    in
    let rec aux_sommets traites =
        match prochain !foret traites with
        | None -> None
        | Some u -> let liste_voisins = del (List.assoc u graphe) traites in
                    match aux_voisins u liste_voisins with
                    | None -> aux_sommets (u::traites)
                    | Some ch -> Some ch
    in
    aux_sommets []

Q11. Écrire contracteG : graphe -> int list -> int -> graphe.
Q12. Montrer que est un couplage de .
Q13. Écrire contracteC : couplage -> int list -> int -> couplage.
Q14. Écrire find : foret -> int -> (int list) option (chemin d'une racine à v), en .
Q15. Écrire extend : foret -> int -> int -> foret (nouvel enfant v sous chaque u), en .
Q16. Montrer que la suite renvoyée au cas (3)(b)(i) est un chemin d'augmentation.
Q17. Code de la ligne 15.
Q18. Code des lignes 17--18.
Q19. Écrire extrait : int list -> int list -> int list (bourgeon de la ligne 20).
Q20. Code des lignes 24--26.
Q21. Écrire edmonds : graphe -> couplage, qui renvoie un couplage maximal.

Corrigé

Q11. On parcourt le graphe une fois : un sommet de lst disparaît, et sa liste d'adjacence est versée dans celle, en construction, de ; un autre sommet est gardé, sa liste d'adjacence étant renommée. À la fin, la liste accumulée est renommée (les sommets de lst deviennent , doublons supprimés), puis privée de lui-même.


let contracteG grph lst w =
  (* voisins_w : concaténation des listes d'adjacence des sommets de lst *)
  let rec parcours g voisins_w =
    match g with
    | [] -> [(w, del (renomme voisins_w lst w) [w])]
    | (a, adj) :: reste ->
        if List.mem a lst then parcours reste (concat adj voisins_w)
        else (a, renomme adj lst w) :: parcours reste voisins_w
  in
  parcours grph []

Correction. Les clefs du résultat sont les sommets hors de lst, plus (nouveau, donc clefs uniques). Pour , renomme adj lst w contient ses voisins hors de et, s'il a au moins un voisin dans , le sommet , une seule fois : ce sont exactement ses voisins dans . La liste de contient, sans doublon, les voisins des sommets de qui ne sont pas dans (ceux de sont devenus , retiré par del) : c'est exactement la définition. Le graphe obtenu est bien symétrique. Exécuté : le triangle muni de l'arête pendante , contracté par et , donne [(3,[9]);(9,[3])].

Q12. Notons le bourgeon, de longueur , et le nouveau sommet.

Un fait sur . Les arêtes de du cycle sont deux à deux disjointes ( est un couplage) ; elles couvrent donc sommets distincts de , et le sommet restant est la base . Tout sommet est ainsi apparié à l'intérieur de , et, étant un couplage, c'est sa seule arête de : la seule arête de pouvant joindre à l'extérieur de est l'arête de en , s'il y en a une.

Les éléments de sont des arêtes de . Une arête avec est une arête de hors de ; une arête avec et , , relie , voisin dans d'un sommet de , à .

Disjonction. Soit un sommet de .

est donc un couplage de .

Q13. Quatre cas selon l'appartenance des extrémités au bourgeon, en recodant l'arête avec la fonction arete de Q9 :


let rec contracteC cpl brg w =
  match cpl with
  | [] -> []
  | (a, b) :: reste ->
      let suite = contracteC reste brg w in
      match List.mem a brg, List.mem b brg with
      | false, false -> (a, b) :: suite       (* arête hors du bourgeon *)
      | true, false -> arete b w :: suite     (* b relié au bourgeon *)
      | false, true -> arete a w :: suite     (* a relié au bourgeon *)
      | true, true -> suite                   (* arête interne : supprimée *)

Chaque arête de cpl est traitée exactement selon la définition de ; par Q12, au plus une arête est renommée vers , donc le résultat n'a pas de doublon. Exécuté : contracteC [(1,2);(3,4);(0,7)] [0;1;2] 9 donne [(3,4);(7,9)].

100 % gratuit

La suite du corrigé est sur Adloun

Le corrigé rédigé en entier, question par question, et le tuteur pour poser des questions sur ce sujet.

Voir le corrigé complet, gratuitement

Inscription gratuite en 30 secondes (e-mail, nom d'utilisateur, mot de passe, classe ou profil), sans carte bancaire : arrivée directe sur le corrigé.

Toutes les parties de l'épreuve

Corrigé complet gratuit →