{
  "chapter": {
    "id": "graphes",
    "level": "terminale",
    "theme": "Structures de données",
    "title": "Graphes",
    "description": "Définition d'un graphe (sommets, arêtes), graphes orientés\net non orientés, pondérés, représentations (matrice\nd'adjacence, liste d'adjacence), parcours en largeur\net en profondeur, plus court chemin, applications.",
    "parties": [
      {
        "id": "modelisation",
        "title": "Modélisation et vocabulaire"
      },
      {
        "id": "representation",
        "title": "Représentations"
      },
      {
        "id": "parcours",
        "title": "Parcours, chemins et connexité"
      }
    ],
    "prerequisites": [],
    "references": []
  },
  "questions": [
    {
      "id": "q01",
      "difficulty": 1,
      "skills": [
        "definition"
      ],
      "title": "Définition d'un graphe",
      "partie": "modelisation",
      "statement": "Qu'est-ce qu'un **graphe** en informatique ?",
      "options": [
        {
          "text": "Un type d'arbre",
          "correct": false,
          "feedback": "Erreur : c'est plutôt l'inverse. Un arbre est un\ncas particulier de graphe (acyclique connexe).\n"
        },
        {
          "text": "Une représentation visuelle de données numériques (camembert, histogramme)",
          "correct": false,
          "feedback": "Erreur : ce serait un **graphique**. Un graphe en\ninformatique est une structure mathématique\ndifférente.\n"
        },
        {
          "text": "Des sommets reliés par des arêtes",
          "correct": true,
          "feedback": "Bonne réponse : c'est la définition mathématique\nstandard. Un graphe modélise n'importe quelle\nrelation entre objets : réseau routier, réseau\nsocial, dépendances de tâches, etc.\n"
        },
        {
          "text": "Un dictionnaire trié",
          "correct": false,
          "feedback": "Un dictionnaire est une\nstructure associant des\nclés à des valeurs, sans\nrapport avec un ensemble\nde sommets reliés par des\narêtes.\n"
        }
      ],
      "explanation": "Les graphes sont omniprésents : transport, réseaux\nsociaux, web (pages reliées par hyperliens), réseaux\nélectriques, planification de tâches, recommandations.\nConnaître les algorithmes de graphes est essentiel."
    },
    {
      "id": "q02",
      "difficulty": 1,
      "skills": [
        "oriente"
      ],
      "title": "Graphe orienté",
      "partie": "modelisation",
      "statement": "Quelle est la différence entre un graphe **orienté** et\nun graphe **non orienté** ?",
      "options": [
        {
          "text": "L'orienté a des arêtes à sens, pas le non orienté",
          "correct": true,
          "feedback": "Bonne réponse : on parle d'**arcs** pour les\narêtes orientées. Exemple orienté : suivre\nquelqu'un sur Twitter (asymétrique). Exemple non\norienté : amitié sur Facebook (symétrique).\n"
        },
        {
          "text": "Un graphe orienté n'a pas de cycle",
          "correct": false,
          "feedback": "Erreur : un graphe orienté **peut** avoir des\ncycles. Sans cycle, on parle de DAG (graphe\norienté acyclique).\n"
        },
        {
          "text": "Le graphe orienté contient plus de sommets",
          "correct": false,
          "feedback": "Erreur : aucun rapport avec le nombre de sommets.\n"
        },
        {
          "text": "Un graphe non orienté est toujours plus rapide à parcourir",
          "correct": false,
          "feedback": "Erreur : la vitesse de parcours dépend du nombre\nde sommets et arêtes, pas de l'orientation.\n"
        }
      ],
      "explanation": "Cas typique : réseau routier (orienté si rues à sens\nunique, non orienté si toutes en double sens). Le\nweb est orienté (un lien va d'une page à l'autre\nsans symétrie)."
    },
    {
      "id": "q03",
      "difficulty": 1,
      "skills": [
        "pondere"
      ],
      "title": "Graphe pondéré",
      "partie": "modelisation",
      "statement": "Qu'est-ce qu'un graphe **pondéré** ?",
      "options": [
        {
          "text": "Un graphe avec beaucoup d'arêtes",
          "correct": false,
          "feedback": "Erreur : c'est plutôt un graphe **dense**. Aucun\nrapport avec « pondéré ».\n"
        },
        {
          "text": "Un graphe partagé entre plusieurs utilisateurs",
          "correct": false,
          "feedback": "Le partage entre\nutilisateurs relève d'un\naspect logiciel sans\nrapport avec la\npondération des arêtes.\n"
        },
        {
          "text": "Un graphe trop lourd à stocker en mémoire",
          "correct": false,
          "feedback": "Erreur : « pondéré » est un terme technique précis,\npas une métaphore.\n"
        },
        {
          "text": "Un graphe où chaque arête porte un poids",
          "correct": true,
          "feedback": "Bonne réponse : par exemple, un GPS représente\nles routes par un graphe pondéré, le poids d'une\nroute étant son temps de trajet. Les algorithmes de\nrecherche du chemin le plus court exploitent ces poids.\n"
        }
      ],
      "explanation": "Un graphe peut être à la fois orienté ET pondéré\n(cas d'un GPS, d'un réseau de transport, etc.)."
    },
    {
      "id": "q04",
      "difficulty": 1,
      "skills": [
        "matrice-adjacence"
      ],
      "title": "Matrice d'adjacence",
      "partie": "representation",
      "statement": "Une **matrice d'adjacence** d'un graphe à $n$ sommets est :",
      "options": [
        {
          "text": "Une matrice $n \\times n$ avec $M[i][j]=1$ si arête $i$-$j$",
          "correct": true,
          "feedback": "Bonne réponse : c'est l'une des deux représentations\nprincipales des graphes. Avantage : test\nd'arête en $O(1)$. Inconvénient : consomme\n$O(n^2)$ d'espace, même pour des graphes creux.\n"
        },
        {
          "text": "Un tableau $1 \\times n$ contenant tous les degrés des sommets",
          "correct": false,
          "feedback": "Erreur : ce serait un tableau de degrés, pas une\nmatrice d'adjacence.\n"
        },
        {
          "text": "Un arbre",
          "correct": false,
          "feedback": "Un arbre est une\nstructure de données\nspécifique, sans rapport\navec la représentation\nd'un graphe par une\nmatrice.\n"
        },
        {
          "text": "Un dictionnaire de listes",
          "correct": false,
          "feedback": "Erreur : c'est plutôt une **liste d'adjacence**.\n"
        }
      ],
      "explanation": "Pour un graphe non orienté, la matrice est\n**symétrique** ($M[i][j] = M[j][i]$). Pour un\ngraphe orienté, elle peut ne pas l'être."
    },
    {
      "id": "q05",
      "difficulty": 1,
      "skills": [
        "liste-adjacence"
      ],
      "title": "Liste d'adjacence",
      "partie": "representation",
      "statement": "Une **liste d'adjacence** d'un graphe consiste à :",
      "options": [
        {
          "text": "Stocker uniquement les sommets isolés du graphe entier",
          "correct": false,
          "feedback": "Erreur : on stocke tous les sommets.\n"
        },
        {
          "text": "Trier les sommets par degré",
          "correct": false,
          "feedback": "Erreur : aucun tri requis.\n"
        },
        {
          "text": "Numéroter les arêtes de $1$ à $m$",
          "correct": false,
          "feedback": "Erreur : c'est plutôt une numérotation, pas une\nliste d'adjacence.\n"
        },
        {
          "text": "Stocker pour chaque sommet la liste de ses voisins",
          "correct": true,
          "feedback": "Bonne réponse : pour le sommet $v$, on stocke la\nliste de tous les sommets directement reliés à\nlui. Plus efficace en mémoire que la matrice\nd'adjacence pour les graphes **creux**\n(peu d'arêtes par sommet). Espace : $O(n + m)$\navec $m$ arêtes.\n"
        }
      ],
      "explanation": "Choix entre matrice et liste : matrice pour graphes\n**denses** (peu de zéros) ou si on a besoin de\ntester très souvent l'existence d'une arête. Liste\npour graphes **creux** (cas le plus fréquent en\npratique)."
    },
    {
      "id": "q06",
      "difficulty": 1,
      "skills": [
        "bfs"
      ],
      "title": "Parcours en largeur",
      "partie": "parcours",
      "statement": "Le parcours en **largeur** d'un graphe :",
      "options": [
        {
          "text": "Visite les voisins par niveaux successifs",
          "correct": true,
          "feedback": "Bonne réponse : c'est l'algorithme de référence\npour explorer un graphe en respectant la distance\nen nombre d'arêtes. Implémentation : avec une\n**file** (FIFO).\n"
        },
        {
          "text": "Parcourt la branche la plus profonde d'abord",
          "correct": false,
          "feedback": "Erreur : c'est le parcours en **profondeur**\n(DFS), pas le parcours en largeur.\n"
        },
        {
          "text": "Trie les sommets par valeur",
          "correct": false,
          "feedback": "Erreur : aucun tri par valeur.\n"
        },
        {
          "text": "Visite uniquement les feuilles",
          "correct": false,
          "feedback": "Erreur : tous les sommets accessibles sont\nvisités.\n"
        }
      ],
      "explanation": "Application clé : trouver le plus court chemin\n**en nombre d'arêtes** depuis un sommet de départ.\nAussi utilisé pour tester la connexité, calculer\nles composantes connexes, etc."
    },
    {
      "id": "q07",
      "difficulty": 1,
      "skills": [
        "dfs"
      ],
      "title": "Parcours en profondeur",
      "partie": "parcours",
      "statement": "Le parcours en **profondeur** d'un graphe :",
      "options": [
        {
          "text": "Explore une branche à fond avant de revenir en arrière",
          "correct": true,
          "feedback": "Bonne réponse : implémentation typique avec une\n**pile** (explicite ou implicite via la\nrécursivité). Le parcours en profondeur sert par\nexemple à repérer un cycle ou à chercher un chemin.\n"
        },
        {
          "text": "Trie les sommets par profondeur",
          "correct": false,
          "feedback": "Erreur : aucun tri par profondeur.\n"
        },
        {
          "text": "Visite tous les voisins du sommet de départ avant d'aller plus loin",
          "correct": false,
          "feedback": "Erreur : c'est le parcours en **largeur**.\n"
        },
        {
          "text": "Calcule la longueur totale du graphe",
          "correct": false,
          "feedback": "Erreur : aucune notion de longueur globale.\n"
        }
      ],
      "explanation": "Mémo : **largeur = file = FIFO** ; **profondeur = pile = LIFO**. Les deux parcours visitent tous les\nsommets accessibles, mais dans un ordre différent."
    },
    {
      "id": "q08",
      "difficulty": 1,
      "skills": [
        "structure-bfs"
      ],
      "title": "Structure utilisée par parcours en largeur",
      "partie": "parcours",
      "statement": "Pour implémenter un parcours en largeur, quelle structure\nde données utilise-t-on naturellement ?",
      "options": [
        {
          "text": "Un dictionnaire",
          "correct": false,
          "feedback": "Erreur : un dictionnaire n'a pas la sémantique\nd'ordre nécessaire.\n"
        },
        {
          "text": "Une pile",
          "correct": false,
          "feedback": "Erreur : la pile correspond au parcours en\n**profondeur**.\n"
        },
        {
          "text": "Une file (FIFO)",
          "correct": true,
          "feedback": "Bonne réponse : on enfile le sommet de départ,\npuis tant que la file n'est pas vide on défile\nun sommet, on visite, et on enfile ses voisins\nnon encore visités. C'est exactement le parcours en largeur.\n"
        },
        {
          "text": "Aucune structure",
          "correct": false,
          "feedback": "Erreur : il faut bien stocker les sommets en\nattente.\n"
        }
      ],
      "explanation": "En Python, une liste peut servir de file :\n`f = [depart]`, puis `f.append(v)` pour enfiler\nà la fin et `f.pop(0)` pour défiler au début.\n`pop(0)` décale tous les éléments restants ; une\nfile implémentée avec deux piles évite ce coût."
    },
    {
      "id": "q09",
      "difficulty": 1,
      "skills": [
        "structure-dfs"
      ],
      "title": "Structure utilisée par parcours en profondeur",
      "partie": "parcours",
      "statement": "Le parcours en profondeur peut s'implémenter en utilisant :",
      "options": [
        {
          "text": "Une file uniquement",
          "correct": false,
          "feedback": "Erreur : la file donne un parcours en largeur,\npas en profondeur.\n"
        },
        {
          "text": "Un graphe profondément imbriqué",
          "correct": false,
          "feedback": "Cette description ne\ncorrespond pas à une\nstructure standard\nutilisée pour le\nparcours d'un graphe.\n"
        },
        {
          "text": "Un arbre binaire",
          "correct": false,
          "feedback": "Erreur : un arbre est une structure différente,\npas l'outil de parcours.\n"
        },
        {
          "text": "Une pile (ou la récursivité)",
          "correct": true,
          "feedback": "Bonne réponse : la récursivité utilise\nimplicitement la pile d'appels. La version\nitérative utilise explicitement une pile (`list`\navec `append` et `pop`).\n"
        }
      ],
      "explanation": "Récursivité = pile implicite. Itératif avec pile =\npile explicite. Les deux donnent le même résultat\n(à l'ordre des voisins près). La version récursive\nest souvent plus claire."
    },
    {
      "id": "q10",
      "difficulty": 1,
      "skills": [
        "chemin"
      ],
      "title": "Plus court chemin",
      "partie": "parcours",
      "statement": "Pour trouver le plus court chemin (en nombre d'arêtes)\nentre deux sommets dans un graphe **non pondéré**, on\nutilise :",
      "options": [
        {
          "text": "Un algorithme glouton qui va toujours vers le voisin le plus connecté",
          "correct": false,
          "feedback": "Erreur : un choix glouton fait à chaque étape ne\ngarantit pas le chemin le plus court : aller vers le\nvoisin qui a le plus de voisins peut éloigner de\nl'arrivée.\n"
        },
        {
          "text": "Un parcours en largeur",
          "correct": true,
          "feedback": "Bonne réponse : le parcours en largeur visite les sommets par\nordre croissant de distance (en arêtes) depuis\nle sommet de départ. Le premier moment où on\natteint le sommet d'arrivée donne la distance\nminimale.\n"
        },
        {
          "text": "Un parcours en profondeur",
          "correct": false,
          "feedback": "Erreur : le parcours en profondeur ne donne pas le plus\ncourt chemin en général. Il peut prendre une route longue.\n"
        },
        {
          "text": "Une recherche dichotomique dans la liste des sommets",
          "correct": false,
          "feedback": "Erreur : la recherche dichotomique trouve une valeur\ndans un tableau trié. Elle ne tient pas compte des\narêtes et ne construit aucun chemin.\n"
        }
      ],
      "explanation": "Le parcours en largeur traite les sommets par distance\ncroissante au départ : d'abord ceux à une arête, puis à\ndeux, et ainsi de suite. Dès qu'il atteint l'arrivée, le\nnombre d'arêtes parcourues est donc minimal."
    },
    {
      "id": "q11",
      "difficulty": 2,
      "skills": [
        "degre"
      ],
      "title": "Degré d'un sommet",
      "partie": "modelisation",
      "statement": "Le **degré** d'un sommet dans un graphe non orienté\nest :",
      "options": [
        {
          "text": "Le nombre d'arêtes incidentes à ce sommet",
          "correct": true,
          "feedback": "Bonne réponse : c'est aussi le nombre de ses voisins\ndans un graphe simple. Par exemple, dans le graphe\n$\\{(A, B), (A, C), (B, C)\\}$, le sommet $A$ est\nde degré $2$. Pour un graphe orienté, on\ndistingue le **degré entrant** et le **degré sortant**.\n"
        },
        {
          "text": "Le poids de l'arête la plus lourde incidente au sommet",
          "correct": false,
          "feedback": "Le degré d'un sommet\nest un nombre d'arêtes,\net non un poids. Le\npoids n'intervient que\ndans les graphes\npondérés, et n'est pas\nlié à la notion de\ndegré.\n"
        },
        {
          "text": "La distance de ce sommet à la racine du graphe",
          "correct": false,
          "feedback": "Erreur : il n'y a pas de racine dans un graphe\ngénéral, et une distance se mesure entre deux\nsommets. Confusion avec les arbres.\n"
        },
        {
          "text": "Sa profondeur dans un parcours en largeur",
          "correct": false,
          "feedback": "Erreur : la profondeur dépend du parcours choisi\net de son sommet de départ, alors que le degré\nest une propriété du sommet lui-même.\n"
        }
      ],
      "explanation": "Théorème classique (Euler) : la somme des degrés\nd'un graphe non orienté est $2m$ (deux fois le\nnombre d'arêtes), car chaque arête contribue $1$ à\ndeux sommets."
    },
    {
      "id": "q12",
      "difficulty": 2,
      "skills": [
        "chemin-cycle"
      ],
      "title": "Cycle dans un graphe",
      "partie": "parcours",
      "statement": "Un **cycle** dans un graphe est :",
      "options": [
        {
          "text": "Un sommet isolé",
          "correct": false,
          "feedback": "Erreur : un sommet isolé n'a aucune arête. Ce\nn'est pas un cycle.\n"
        },
        {
          "text": "Une seule arête répétée plusieurs fois de suite",
          "correct": false,
          "feedback": "Erreur : c'est un multi-graphe, notion\ndifférente.\n"
        },
        {
          "text": "Un sommet de degré pair",
          "correct": false,
          "feedback": "Erreur : pas la définition d'un cycle.\n"
        },
        {
          "text": "Une suite d'arêtes qui revient au départ",
          "correct": true,
          "feedback": "Bonne réponse : par exemple, le chemin\n$A \\to B \\to C \\to A$ forme un cycle. Détecter\nles cycles est important : un graphe sans cycle\nest appelé **acyclique** (DAG si orienté).\n"
        }
      ],
      "explanation": "Un **arbre** est un graphe connexe sans cycle. C'est\ncette absence de cycle qui caractérise l'arbre par\nrapport au graphe général."
    },
    {
      "id": "q13",
      "difficulty": 2,
      "skills": [
        "connexite"
      ],
      "title": "Graphe connexe",
      "partie": "parcours",
      "statement": "Un graphe non orienté est **connexe** quand :",
      "options": [
        {
          "text": "Il est orienté",
          "correct": false,
          "feedback": "Erreur : la connexité concerne les graphes\norientés ET non orientés.\n"
        },
        {
          "text": "Il a beaucoup d'arêtes",
          "correct": false,
          "feedback": "Erreur : la quantité ne suffit pas. C'est la\nstructure qui compte.\n"
        },
        {
          "text": "Un chemin relie toute paire de sommets",
          "correct": true,
          "feedback": "Bonne réponse : on peut « atteindre » n'importe\nquel sommet depuis n'importe quel autre. Si on\nenlève cette propriété, on peut avoir plusieurs\n**composantes connexes** (groupes isolés).\n"
        },
        {
          "text": "Il possède au moins $n$ arêtes au total",
          "correct": false,
          "feedback": "Erreur : un graphe connexe à $n$ sommets a au\nmoins $n - 1$ arêtes (cas de l'arbre), mais\ncela n'est pas suffisant.\n"
        }
      ],
      "explanation": "Le parcours en largeur ou parcours en profondeur depuis un sommet visite toute sa\n**composante connexe**. Si on n'atteint pas tous les\nsommets, le graphe n'est pas connexe."
    },
    {
      "id": "q15",
      "difficulty": 2,
      "skills": [
        "taille-matrice"
      ],
      "title": "Espace mémoire matrice vs liste",
      "partie": "representation",
      "statement": "Pour un graphe à $n = 1000$ sommets et $m = 5000$\narêtes, quelle représentation est la plus économe en\nmémoire ?",
      "options": [
        {
          "text": "La liste d'adjacence ($O(n+m)$)",
          "correct": true,
          "feedback": "Bonne réponse : la liste d'adjacence consomme\nde l'ordre du nombre d'arêtes plus le nombre de\nsommets. Beaucoup mieux que la matrice quand le\ngraphe est **creux** ($m \\ll n^2$), ce qui est\nle cas en pratique pour beaucoup d'applications.\n"
        },
        {
          "text": "La matrice d'adjacence ($O(n^2) = 10^6$ cases)",
          "correct": false,
          "feedback": "Erreur : la matrice consomme bien plus que la\nliste pour un graphe creux. La liste vaut mieux.\n"
        },
        {
          "text": "Aucune différence vraiment notable",
          "correct": false,
          "feedback": "Erreur : la différence est importante, surtout\npour les graphes creux.\n"
        },
        {
          "text": "Cela dépend du langage de programmation",
          "correct": false,
          "feedback": "Erreur : la complexité asymptotique est\nindépendante du langage.\n"
        }
      ],
      "explanation": "Densité d'un graphe : $d = m / \\binom{n}{2}$. Pour\n$d$ proche de $1$ (graphe dense), la matrice peut\nêtre préférable. Pour $d$ proche de $0$ (creux), la\nliste est meilleure."
    },
    {
      "id": "q16",
      "difficulty": 2,
      "skills": [
        "bfs-distance"
      ],
      "title": "Parcours en largeur et distance",
      "partie": "parcours",
      "statement": "Avec un parcours en largeur depuis le sommet $s$, on calcule pour chaque\nsommet $v$ atteignable :",
      "options": [
        {
          "text": "Les sommets isolés",
          "correct": false,
          "feedback": "Erreur : le parcours en largeur ne visite que les\nsommets accessibles depuis $s$.\n"
        },
        {
          "text": "Tous les chemins possibles",
          "correct": false,
          "feedback": "Erreur : trop d'information. Le parcours en largeur\ncalcule uniquement la distance minimale, pas tous les\nchemins.\n"
        },
        {
          "text": "Le poids minimal du chemin $s \\to v$ (si pondéré)",
          "correct": false,
          "feedback": "Erreur : le parcours en largeur calcule la distance\nen **nombre d'arêtes**, sans tenir compte des poids\néventuels.\n"
        },
        {
          "text": "Le nombre minimal d'arêtes du chemin $s \\to v$",
          "correct": true,
          "feedback": "Bonne réponse : c'est précisément ce que calcule le\nparcours en largeur. Très utile dans des graphes où\ntoutes les arêtes sont équivalentes (réseau social,\njeu de plateau, etc.).\n"
        }
      ],
      "explanation": "Au moment où le parcours en largeur découvre un sommet,\nil peut enregistrer (a) la distance, (b) le sommet\n« parent » dans le parcours. Avec cela, on peut\nreconstituer le chemin le plus court en arêtes."
    },
    {
      "id": "q17",
      "difficulty": 2,
      "skills": [
        "reseau-social"
      ],
      "title": "Application réseau social",
      "partie": "modelisation",
      "statement": "Sur un réseau social, on veut trouver tous les amis\n« à distance $2$ » (amis d'amis) d'un utilisateur $u$.\nQuel algorithme utiliser ?",
      "options": [
        {
          "text": "Un parcours en largeur limité à la profondeur $2$",
          "correct": true,
          "feedback": "Bonne réponse : parcours en largeur avec une limite de\nprofondeur. À profondeur $0$ : $u$ ; à $1$ : ses\namis ; à $2$ : les amis des amis (sans compter\n$u$ ni ses amis directs si on veut). Très\nutilisé pour la recommandation d'amis.\n"
        },
        {
          "text": "Un tri des amis par valeur d'identifiant",
          "correct": false,
          "feedback": "Le tri d'une liste n'a\naucun rapport avec la\nrecherche d'amis à une\ndistance donnée dans un\nréseau social.\n"
        },
        {
          "text": "Un parcours en profondeur sans limite",
          "correct": false,
          "feedback": "Erreur : parcours en profondeur n'organise pas les visites par\nniveaux ; difficile d'extraire « distance $2$ ».\n"
        },
        {
          "text": "Une recherche dichotomique",
          "correct": false,
          "feedback": "Erreur : la dichotomie suppose une structure\nordonnée, ce qui n'est pas le cas d'un graphe\nsocial.\n"
        }
      ],
      "explanation": "Cette technique est utilisée par LinkedIn, Facebook,\netc. La théorie des « six degrés de séparation »\naffirme que dans le graphe social mondial, la\ndistance maximale est environ $6$."
    },
    {
      "id": "q18",
      "difficulty": 2,
      "skills": [
        "implementation-dictionnaire"
      ],
      "title": "Liste d'adjacence en Python",
      "partie": "representation",
      "statement": "Comment représenter naturellement une liste d'adjacence\nen Python ?",
      "options": [
        {
          "text": "Comme un entier codant le nombre total d'arêtes",
          "correct": false,
          "feedback": "Erreur : un entier ne résume qu'une quantité. Il ne\ndit pas quels sommets sont reliés entre eux.\n"
        },
        {
          "text": "Comme un tuple unique contenant tous les sommets",
          "correct": false,
          "feedback": "Erreur : on saurait quels sommets existent, mais pas\nlesquels sont voisins. Un tuple, immuable, ne permet\npas non plus d'ajouter une arête.\n"
        },
        {
          "text": "Comme une chaîne de caractères énumérant les arêtes",
          "correct": false,
          "feedback": "Erreur : il faudrait analyser le texte à chaque\naccès aux voisins. Difficile à manipuler et\ninefficace.\n"
        },
        {
          "text": "Comme un dictionnaire sommet vers liste de voisins",
          "correct": true,
          "feedback": "Bonne réponse : par exemple,\n`g = {'A': ['B', 'C'], 'B': ['A'], 'C': ['A']}`.\nTrès lisible et efficace. On accède aux voisins\nen $O(1)$ via la clé.\n"
        }
      ],
      "explanation": "Variante orientée objet : créer une classe `Graphe`\navec méthodes `ajouter_sommet`, `ajouter_arete`,\n`voisins`, etc. Plus propre pour des projets\nstructurés. Mais en NSI, le dictionnaire suffit\nsouvent."
    },
    {
      "id": "q19",
      "difficulty": 2,
      "skills": [
        "parcours-implementation"
      ],
      "title": "Code parcours en largeur",
      "partie": "parcours",
      "statement": "Quelle fonction Python implémente correctement un parcours en largeur\ndepuis un sommet `depart` dans un graphe `g` (dictionnaire) ?",
      "options": [
        {
          "text": "```python\ndef parcours_largeur(g, depart):\n    visites = [depart]\n    pile = [depart]\n    while len(pile) > 0:\n        v = pile.pop()\n        for w in g[v]:\n            if w not in visites:\n                visites.append(w)\n                pile.append(w)\n    return visites\n```",
          "correct": false,
          "feedback": "Erreur : `pile.pop()` retire le **dernier**\nélément ajouté : la liste sert de pile (LIFO), et les\nsommets ne sont plus traités par distance croissante au\ndépart. Le parcours en largeur exige une file (FIFO),\ndont on retire le **premier** élément avec `pop(0)`.\n"
        },
        {
          "text": "```python\ndef parcours_largeur(g, depart):\n    visites = [depart]\n    file = [depart]\n    while len(file) > 0:\n        v = file.pop(0)\n        for w in g[v]:\n            if w not in visites:\n                visites.append(w)\n                file.append(w)\n    return visites\n```",
          "correct": true,
          "feedback": "Bonne réponse : `file.pop(0)` retire le sommet ajouté\nle plus tôt, ce qui impose le parcours en largeur. La\nliste `visites` évite de réenfiler un sommet déjà\nrencontré, donc de boucler sur un graphe avec cycle.\n"
        },
        {
          "text": "```python\ndef parcours_largeur(g, depart):\n    return g[depart]\n```",
          "correct": false,
          "feedback": "Erreur : retourne uniquement les voisins\ndirects, pas le parcours complet.\n"
        },
        {
          "text": "```python\ndef parcours_largeur(g, depart):\n    file = [depart]\n    resultat = []\n    while len(file) > 0:\n        v = file.pop(0)\n        resultat.append(v)\n        for w in g[v]:\n            file.append(w)\n    return resultat\n```",
          "correct": false,
          "feedback": "Erreur : sans liste `visites`, chaque\nsommet est réenfilé à chaque fois qu'on le\nrencontre : sur un graphe avec cycle, la\nboucle ne termine jamais. Le marquage des\nsommets visités est indispensable.\n"
        }
      ],
      "explanation": "La liste `visites` est cruciale : sans elle, sur un\ngraphe avec cycle, on bouclerait indéfiniment.\nC'est l'une des erreurs classiques sur les graphes."
    },
    {
      "id": "q20",
      "difficulty": 2,
      "skills": [
        "arbre-vs-graphe"
      ],
      "title": "Arbre comme cas particulier",
      "partie": "modelisation",
      "statement": "Un **arbre** (au sens informatique) est un cas\nparticulier de :",
      "options": [
        {
          "text": "Un graphe connexe acyclique",
          "correct": true,
          "feedback": "Bonne réponse : tous les concepts d'arbre\n(racine, hauteur, parcours) sont applicables aux\ngraphes plus généralement, mais l'arbre garantit\ndes propriétés (chemin unique entre deux\nsommets) qui simplifient les algorithmes.\n"
        },
        {
          "text": "Un tableau linéaire à une dimension",
          "correct": false,
          "feedback": "Erreur : un tableau est linéaire, un arbre\nhiérarchique.\n"
        },
        {
          "text": "Une file (premier entré, premier sorti)",
          "correct": false,
          "feedback": "Erreur : une file est une structure linéaire,\nsans branchement. File et arbre sont distincts.\n"
        },
        {
          "text": "Une pile (dernier entré, premier sorti)",
          "correct": false,
          "feedback": "Erreur : une pile est linéaire elle aussi. Pile\net arbre sont des structures totalement\ndifférentes.\n"
        }
      ],
      "explanation": "Tout arbre à $n$ sommets a exactement $n - 1$\narêtes. Si l'on a $n$ sommets, $n - 1$ arêtes et la\nconnexité, alors c'est un arbre (et donc sans\ncycle). Triple caractérisation."
    },
    {
      "id": "q21",
      "difficulty": 3,
      "skills": [
        "modelisation",
        "graphe-non-oriente"
      ],
      "title": "Modéliser des conflits d'examens",
      "partie": "modelisation",
      "statement": "Un lycée organise ses épreuves de rattrapage. Deux épreuves ne\npeuvent pas avoir lieu en même temps si un élève doit passer les\ndeux. Pour préparer le planning, on veut représenter ces\nincompatibilités par un graphe. Quelle modélisation convient ?",
      "options": [
        {
          "text": "Un sommet par élève, une arête entre deux élèves qui passent une même épreuve",
          "correct": false,
          "feedback": "Erreur : ce graphe relie des élèves, alors que la contrainte porte\nsur des épreuves. On ne pourrait pas y lire directement quelles\népreuves sont incompatibles.\n"
        },
        {
          "text": "Un sommet par épreuve, une arête entre deux épreuves qui ont un élève en commun",
          "correct": true,
          "feedback": "Bonne réponse : les objets à placer sont les épreuves, et la\nrelation « ne pas avoir lieu en même temps » est symétrique, d'où un\ngraphe non orienté. Deux épreuves reliées par une arête devront\noccuper des créneaux différents.\n"
        },
        {
          "text": "Un sommet par épreuve, un arc d'une épreuve vers celle qui doit la suivre",
          "correct": false,
          "feedback": "Erreur : l'énoncé n'impose aucun ordre entre les épreuves, seulement\nune incompatibilité. Cette relation est symétrique : un graphe\norienté ajouterait un sens qui n'existe pas.\n"
        },
        {
          "text": "Un sommet par créneau horaire, une arête entre deux créneaux consécutifs",
          "correct": false,
          "feedback": "Erreur : les créneaux sont ce que l'on cherche à attribuer, pas les\ndonnées du problème. Relier des créneaux consécutifs ne dit rien des\nélèves communs aux épreuves.\n"
        }
      ],
      "explanation": "Pour modéliser une situation par un graphe, on choisit les sommets\nparmi les objets étudiés, ici les épreuves, et les arêtes selon la\nrelation qui les lie, ici avoir un élève en commun. Une relation\nsymétrique donne un graphe non orienté."
    },
    {
      "id": "q25",
      "difficulty": 3,
      "skills": [
        "parcours",
        "chemin",
        "synthese"
      ],
      "title": "Savoir si deux villes sont reliées",
      "partie": "parcours",
      "statement": "Sur une carte, les routes entre villes portent des longueurs en\nkilomètres. On veut seulement savoir s'il existe un chemin de la\nville `A` à la ville `B`, quelle que soit sa longueur. Quelle méthode\nconvient ?",
      "options": [
        {
          "text": "Seulement un parcours en largeur, le seul qui trouve des chemins",
          "correct": false,
          "feedback": "Erreur : le parcours en largeur trouve les chemins au plus petit\nnombre d'arêtes, mais la question ne porte que sur l'existence d'un\nchemin. Le parcours en profondeur visite lui aussi tous les sommets\naccessibles depuis `A`.\n"
        },
        {
          "text": "Seulement un parcours en profondeur, qui suit chaque route jusqu'au bout",
          "correct": false,
          "feedback": "Erreur : le parcours en profondeur convient, mais il n'est pas le\nseul. Tout parcours depuis `A` visite exactement les sommets\naccessibles, et le parcours en largeur répond donc aussi.\n"
        },
        {
          "text": "L'un ou l'autre parcours depuis `A`, en vérifiant si `B` est visité",
          "correct": true,
          "feedback": "Bonne réponse : les deux parcours visitent tous les sommets\naccessibles depuis `A`, dans des ordres différents. `B` est visité\nsi et seulement si un chemin mène de `A` à `B`.\n"
        },
        {
          "text": "Aucun parcours : il faut d'abord tenir compte des longueurs des routes",
          "correct": false,
          "feedback": "Erreur : l'existence d'un chemin ne dépend pas des longueurs,\nseulement des routes présentes. Les longueurs ne servent que si l'on\ncherche le chemin le plus court en kilomètres.\n"
        }
      ],
      "explanation": "Pour savoir si deux sommets sont reliés, un parcours suffit : il\nvisite tous les sommets accessibles depuis le départ. Le choix entre\nlargeur et profondeur n'importe que si l'on veut, en plus, un chemin\nau nombre d'arêtes minimal."
    },
    {
      "id": "q26",
      "difficulty": 2,
      "skills": [
        "conversion-representation"
      ],
      "title": "Conversion entre représentations",
      "partie": "representation",
      "statement": "Soit le graphe non orienté représenté par la\nliste d'adjacence\n`g = {'A': ['B', 'C'], 'B': ['A', 'C'], 'C': ['A', 'B']}`.\nQuelle est la matrice d'adjacence correspondante\navec l'ordre des sommets `[A, B, C]` ?",
      "options": [
        {
          "text": "```python\n[[0, 1, 0],\n [1, 0, 1],\n [0, 1, 0]]\n```\n",
          "correct": false,
          "feedback": "Erreur : cette matrice correspondrait à un\ngraphe en chaîne `A - B - C`, où `A` et `C`\nne sont pas directement reliés. Or le graphe\ndonné est complet : `A` et `C` sont voisins.\n"
        },
        {
          "text": "```python\n[[0, 1, 1],\n [1, 0, 1],\n [1, 1, 0]]\n```\n",
          "correct": true,
          "feedback": "Bonne réponse : chaque sommet est relié à\nchacun des deux autres (graphe complet $K_3$).\nLa diagonale est nulle (pas de boucle), et la\nmatrice est symétrique (graphe non orienté).\nToutes les autres cases valent $1$ car les\narêtes existent dans tous les sens.\n"
        },
        {
          "text": "```python\n[[0, 0, 0],\n [0, 0, 0],\n [0, 0, 0]]\n```\n",
          "correct": false,
          "feedback": "Erreur : ce serait un graphe sans aucune\narête. Or le graphe possède bien des arêtes\n(chaque sommet a des voisins dans la liste\nd'adjacence).\n"
        },
        {
          "text": "```python\n[[1, 1, 1],\n [1, 1, 1],\n [1, 1, 1]]\n```\n",
          "correct": false,
          "feedback": "Erreur : la diagonale ne doit pas être à $1$\ncar aucun sommet n'a de boucle sur lui-même\n(par exemple, `g['A']` ne contient pas `'A'`).\n"
        }
      ],
      "explanation": "Pour un graphe non orienté, la matrice\nd'adjacence est toujours **symétrique**. Pour un\ngraphe orienté, ce n'est pas nécessairement le\ncas. Les deux représentations sont équivalentes\nen information ; le choix dépend des opérations\nles plus fréquentes (test d'arête en O(1) avec\nla matrice ; énumération des voisins efficace\navec la liste)."
    },
    {
      "id": "q28",
      "difficulty": 2,
      "skills": [
        "trace-bfs"
      ],
      "title": "Trace d'un parcours en largeur",
      "partie": "parcours",
      "statement": "On effectue un parcours en largeur du graphe\n`g = {'A': ['B', 'C'], 'B': ['A', 'D'], 'C': ['A', 'D'], 'D': ['B', 'C', 'E'], 'E': ['D']}`\nen partant de `'A'`, en visitant les voisins\ndans l'ordre où ils apparaissent dans la liste.\nDans quel ordre les sommets sont-ils visités ?",
      "options": [
        {
          "text": "A, B, C, D, E\n",
          "correct": true,
          "feedback": "Bonne réponse : on commence par enfiler `A`,\npuis on défile `A` et on enfile ses voisins\n`B` et `C`. On défile `B`, on enfile `D`\n(`A` est déjà visité). On défile `C` (ses\nvoisins `A` et `D` sont déjà visités ou\nenfilés). On défile `D`, on enfile `E`. On\ndéfile `E`. Ordre de visite : A, B, C, D, E.\n"
        },
        {
          "text": "A, B, D, E, C\n",
          "correct": false,
          "feedback": "Erreur : c'est un parcours en **profondeur**\n(qui suit une branche en suivant les\nvoisins). Le parcours en largeur, lui,\nvisite les sommets par niveaux croissants\nde distance, pas en plongeant.\n"
        },
        {
          "text": "A, C, B, D, E\n",
          "correct": false,
          "feedback": "Erreur : on visite les voisins dans l'ordre\noù ils apparaissent dans la liste. Pour `A`,\nc'est `B` puis `C`. Donc `B` est visité\navant `C`, pas l'inverse.\n"
        },
        {
          "text": "A, B, C, E, D\n",
          "correct": false,
          "feedback": "Erreur : on visite `D` avant `E` car `D` est\nenfilé en premier (par `B`), et `E` n'est\nenfilé que plus tard (quand on visite `D`).\nL'ordre est donc D avant E.\n"
        }
      ],
      "explanation": "Le parcours en largeur visite les sommets dans\nl'ordre croissant de leur distance (en arêtes)\nau sommet de départ. Niveau $0$ : $A$. Niveau\n$1$ : $B$, $C$. Niveau $2$ : $D$. Niveau $3$ :\n$E$. C'est exactement ce qui justifie l'usage\ndu parcours en largeur pour calculer les plus\ncourts chemins en nombre d'arêtes."
    },
    {
      "id": "q29",
      "difficulty": 3,
      "skills": [
        "parcours-largeur",
        "chemin",
        "lecture-code"
      ],
      "title": "Reconstituer un chemin grâce aux parents",
      "partie": "parcours",
      "statement": "On considère le graphe `g` et la fonction suivants :\n\n```python\ng = {\"A\": [\"B\", \"C\"], \"B\": [\"A\", \"D\"], \"C\": [\"A\", \"E\"],\n     \"D\": [\"B\", \"E\"], \"E\": [\"C\", \"D\"]}\n\ndef chemin(g, depart, arrivee):\n    parent = {depart: depart}\n    file = [depart]\n    while len(file) > 0:\n        s = file.pop(0)\n        for v in g[s]:\n            if v not in parent:\n                parent[v] = s\n                file.append(v)\n    resultat = [arrivee]\n    s = arrivee\n    while s != depart:\n        s = parent[s]\n        resultat.append(s)\n    return resultat\n```\n\nQue renvoie `chemin(g, \"A\", \"E\")` ?",
      "options": [
        {
          "text": "`['A', 'C', 'E']`",
          "correct": false,
          "feedback": "Erreur : le chemin passe bien par `C`, mais la fonction le construit\nà reculons, en partant de `arrivee` et en remontant les parents. La\nliste commence donc par `'E'`.\n"
        },
        {
          "text": "`['E', 'C', 'A']`",
          "correct": true,
          "feedback": "Bonne réponse : le parcours enregistre `'A'` comme parent de `'B'`\net de `'C'`, puis `'B'` comme parent de `'D'` et `'C'` comme parent\nde `'E'`, car `C` sort de la file avant `D`. En remontant depuis\n`E`, on obtient `E`, `C`, puis `A`.\n"
        },
        {
          "text": "`['E', 'D', 'B', 'A']`",
          "correct": false,
          "feedback": "Erreur : `E` est découvert depuis `C`, qui sort de la file avant\n`D`. Son parent est donc `C` et non `D`, et le chemin reconstitué\nne passe pas par `B`.\n"
        },
        {
          "text": "`['A', 'B', 'D', 'E']`",
          "correct": false,
          "feedback": "Erreur : ce chemin compte trois arêtes alors que `A → C → E` n'en\ncompte que deux, et la fonction renvoie la liste en partant de\n`arrivee`. Le parcours en largeur retient un chemin au nombre\nd'arêtes minimal.\n"
        }
      ],
      "explanation": "Pendant un parcours en largeur, noter pour chaque sommet celui qui\nl'a découvert permet de reconstituer un chemin au nombre d'arêtes\nminimal. La reconstruction part de l'arrivée et remonte les\nparents : la liste obtenue suit l'ordre inverse du trajet."
    },
    {
      "id": "q30",
      "difficulty": 2,
      "skills": [
        "code-dfs-recursif"
      ],
      "title": "Code du parcours en profondeur récursif",
      "partie": "parcours",
      "statement": "Quel code Python implémente correctement un\nparcours en profondeur récursif d'un graphe `g`\n(dictionnaire d'adjacence) à partir d'un sommet\n`depart`, appelé sous la forme\n`parcours_profondeur(g, depart, [])` ?",
      "options": [
        {
          "text": "```python\ndef parcours_profondeur(g, depart, visites):\n    visites.append(depart)\n    for voisin in g[depart]:\n        if voisin not in visites:\n            parcours_profondeur(g, voisin, visites)\n    return visites\n```",
          "correct": true,
          "feedback": "Bonne réponse : on marque le sommet courant en l'ajoutant\nà `visites`, puis on appelle récursivement la fonction sur\nchaque voisin non encore visité, en transmettant la même\nliste. La récursivité utilise implicitement la pile\nd'appels, ce qui réalise le LIFO du parcours en\nprofondeur. Sur le graphe\n`g = {\"A\": [\"B\", \"C\"], \"B\": [\"A\", \"D\"], \"C\": [\"A\", \"D\"], \"D\": [\"B\", \"C\"]}`,\nl'appel `parcours_profondeur(g, \"A\", [])` renvoie\n`['A', 'B', 'D', 'C']`.\n"
        },
        {
          "text": "```python\ndef parcours_profondeur(g, depart, visites):\n    visites.append(depart)\n    for voisin in g[depart]:\n        parcours_profondeur(g, voisin, visites)\n    return visites\n```",
          "correct": false,
          "feedback": "Erreur : aucun test avant l'appel récursif. Dans un graphe\nnon orienté, `B` est voisin de `A` et `A` voisin de `B` :\nla fonction repasse sans fin par les mêmes sommets et\nfinit par lever `RecursionError`.\n"
        },
        {
          "text": "```python\ndef parcours_profondeur(g, depart, visites):\n    visites.append(depart)\n    for voisin in g[depart]:\n        if voisin not in visites:\n            parcours_profondeur(g, voisin, [])\n    return visites\n```",
          "correct": false,
          "feedback": "Erreur : l'appel récursif transmet une nouvelle liste\nvide au lieu de `visites`, donc chaque appel oublie les\nsommets déjà vus. Dès qu'une arête peut être parcourue\ndans les deux sens, la fonction repasse sans fin par les\nmêmes sommets et l'appel finit sur `RecursionError`.\n"
        },
        {
          "text": "```python\ndef parcours_profondeur(g, depart, visites):\n    visites.append(depart)\n    for voisin in g[depart]:\n        if voisin not in visites:\n            return parcours_profondeur(g, voisin, visites)\n    return visites\n```",
          "correct": false,
          "feedback": "Erreur : le `return` placé dans la boucle arrête\nl'exploration après le premier voisin non visité. Sur\n`{\"A\": [\"B\", \"C\"], \"B\": [\"A\"], \"C\": [\"A\"]}`, l'appel\ndepuis `A` renvoie `['A', 'B']` et oublie `C`.\n"
        }
      ],
      "explanation": "Un parcours en profondeur récursif marque le sommet\ncourant, puis se relance sur chaque voisin non visité en\npartageant la même liste `visites`. Pour de très grands\ngraphes, on peut remplacer la récursion par une pile\nexplicite, ce qui évite `RecursionError`."
    },
    {
      "id": "q22",
      "difficulty": 3,
      "skills": [
        "synthese",
        "parcours-profondeur",
        "trace"
      ],
      "title": "Trace d'un parcours en profondeur",
      "partie": "modelisation",
      "statement": "On effectue un parcours en profondeur récursif depuis\nle sommet $A$ sur le graphe non orienté suivant :\n\n- $A$ est relié à $B$ et $C$ ;\n- $B$ est relié à $D$ ;\n- $C$ est relié à $D$ et $E$ ;\n- $D$ est relié à $E$.\n\nOn suppose que, à chaque sommet visité, les voisins sont\nexaminés dans l'ordre alphabétique. Dans quel ordre les\nsommets sont-ils découverts ?",
      "options": [
        {
          "text": "$A, B, D, C, E$",
          "correct": true,
          "feedback": "Bonne réponse : on s'enfonce d'abord. Depuis $A$,\non visite $B$ (premier voisin alphabétique), puis\n$D$ (seul voisin non vu de $B$). Depuis $D$, les\nvoisins non vus sont $C$ et $E$ : l'alphabet impose\n$C$, dont le seul voisin non vu est $E$.\n"
        },
        {
          "text": "$A, B, C, D, E$",
          "correct": false,
          "feedback": "Erreur : c'est la trace du parcours en **largeur**\n(par couches : $B$ et $C$ voisins de $A$, puis $D$,\npuis $E$). En profondeur, on descend via $B$ puis\n$D$ avant de revenir à $C$.\n"
        },
        {
          "text": "$A, B, D, E, C$",
          "correct": false,
          "feedback": "Erreur : depuis $D$, les voisins non visités sont\n$C$ et $E$ ; l'ordre alphabétique impose de\ndescendre par $C$ avant $E$.\n"
        },
        {
          "text": "$A, C, D, B, E$",
          "correct": false,
          "feedback": "Erreur : trace d'un parcours en profondeur qui\nexaminerait $C$ avant $B$ ; or l'ordre alphabétique\nimpose $B$ comme premier voisin de $A$.\n"
        }
      ],
      "explanation": "Le parcours en profondeur (DFS) s'enfonce le long d'une\nbranche avant de revenir en arrière (pile ou récursion),\nlà où le parcours en largeur (file) progresse par\ncouches : sur ce même graphe, la largeur donnerait\n$A, B, C, D, E$. Comparer les deux traces sur un même\ngraphe est le meilleur moyen de les distinguer."
    },
    {
      "id": "q23",
      "difficulty": 3,
      "skills": [
        "synthese",
        "representation",
        "complexite"
      ],
      "title": "Choisir entre matrice et liste d'adjacence",
      "partie": "modelisation",
      "statement": "On souhaite stocker un graphe non orienté représentant\nun réseau social : environ un million d'utilisateurs\n(sommets) et en moyenne une centaine de contacts par\npersonne (graphe creux, environ $10^8$ arêtes au total).\nQuelle représentation est la plus adaptée en pratique ?",
      "options": [
        {
          "text": "Une liste d'adjacence, la matrice serait bien trop énorme",
          "correct": true,
          "feedback": "Bonne réponse : une matrice d'adjacence à $10^6$\nsommets occupe $10^{12}$ cases, soit environ un\ntéraoctet pour un seul bit par case, ce qui est\ninenvisageable. Une liste d'adjacence ne stocke que\nles arêtes réellement présentes (environ $10^8$),\nce qui reste dans des ordres de grandeur\nmanipulables.\n"
        },
        {
          "text": "Une matrice d'adjacence, car elle permet de tester l'existence d'une arête en temps constant",
          "correct": false,
          "feedback": "Erreur : le temps constant pour tester l'existence\nd'une arête est un avantage théorique réel, mais la\ntaille de la matrice ($10^{12}$ cases) la rend\ninutilisable sur un graphe d'un million de sommets.\n"
        },
        {
          "text": "Une matrice d'adjacence, car elle est plus simple à implémenter et à comprendre",
          "correct": false,
          "feedback": "Erreur : la simplicité d'implémentation ne compense\npas un coût mémoire prohibitif. Le critère décisif\ndans ce scénario est la consommation mémoire.\n"
        },
        {
          "text": "Aucune des deux représentations n'est utilisable à cette taille de graphe",
          "correct": false,
          "feedback": "Erreur : la liste d'adjacence est exactement la\nstructure que tous les moteurs de réseaux sociaux\nutilisent en pratique. Elle tient parfaitement en\nmémoire pour un graphe creux à un million de\nsommets.\n"
        }
      ],
      "explanation": "Règle générale : pour un graphe **dense** (beaucoup\nd'arêtes par rapport au carré du nombre de sommets),\nla matrice d'adjacence est compétitive ; pour un\ngraphe **creux**, la liste d'adjacence l'emporte tant\nen mémoire qu'en temps pour la plupart des\nalgorithmes (parcours, plus courts chemins)."
    },
    {
      "id": "q31",
      "difficulty": 2,
      "skills": [
        "representation",
        "matrice",
        "aretes",
        "calcul"
      ],
      "title": "Compter les arêtes dans une matrice d'adjacence",
      "partie": "representation",
      "statement": "La matrice d'adjacence d'un graphe non orienté à quatre sommets\ncontient $6$ coefficients égaux à $1$. Combien le graphe a-t-il\nd'arêtes ?",
      "options": [
        {
          "text": "$3$, chaque arête comptant deux fois",
          "correct": true,
          "feedback": "Bonne réponse : une arête entre $i$ et $j$ met un $1$ en\nposition $(i, j)$ et un autre en $(j, i)$ ; $6 / 2 = 3$.\n"
        },
        {
          "text": "$6$, un par coefficient égal à $1$",
          "correct": false,
          "feedback": "Erreur : la matrice est symétrique, chaque arête apparaît deux\nfois.\n"
        },
        {
          "text": "$12$, deux par coefficient égal à $1$",
          "correct": false,
          "feedback": "Erreur : c'est l'inverse, deux coefficients pour une arête.\n"
        },
        {
          "text": "$16$, un par coefficient de la matrice",
          "correct": false,
          "feedback": "Erreur : les coefficients nuls ne représentent aucune arête.\n"
        }
      ],
      "explanation": "Dans un graphe non orienté, la somme des coefficients de la matrice\nvaut deux fois le nombre d'arêtes.",
      "variants": [
        {
          "statement": "La matrice d'adjacence d'un graphe non orienté à quatre sommets\ncontient $6$ coefficients égaux à $1$. Combien le graphe a-t-il\nd'arêtes ?",
          "options": [
            {
              "text": "$3$, chaque arête comptant deux fois",
              "correct": true,
              "feedback": "Bonne réponse : une arête entre $i$ et $j$ met un $1$ en\nposition $(i, j)$ et un autre en $(j, i)$ ; $6 / 2 = 3$.\n"
            },
            {
              "text": "$6$, un par coefficient égal à $1$",
              "correct": false,
              "feedback": "Erreur : la matrice est symétrique, chaque arête apparaît deux\nfois.\n"
            },
            {
              "text": "$12$, deux par coefficient égal à $1$",
              "correct": false,
              "feedback": "Erreur : c'est l'inverse, deux coefficients pour une arête.\n"
            },
            {
              "text": "$16$, un par coefficient de la matrice",
              "correct": false,
              "feedback": "Erreur : les coefficients nuls ne représentent aucune arête.\n"
            }
          ],
          "explanation": "Dans un graphe non orienté, la somme des coefficients de la matrice\nvaut deux fois le nombre d'arêtes."
        },
        {
          "statement": "La matrice d'adjacence d'un graphe non orienté à quatre sommets\ncontient $10$ coefficients égaux à $1$. Combien le graphe a-t-il\nd'arêtes ?",
          "options": [
            {
              "text": "$5$, chaque arête comptant deux fois",
              "correct": true,
              "feedback": "Bonne réponse : une arête entre $i$ et $j$ met un $1$ en\nposition $(i, j)$ et un autre en $(j, i)$ ; $10 / 2 = 5$.\n"
            },
            {
              "text": "$10$, un par coefficient égal à $1$",
              "correct": false,
              "feedback": "Erreur : la matrice est symétrique, chaque arête apparaît deux\nfois.\n"
            },
            {
              "text": "$20$, deux par coefficient égal à $1$",
              "correct": false,
              "feedback": "Erreur : c'est l'inverse, deux coefficients pour une arête.\n"
            },
            {
              "text": "$16$, un par coefficient de la matrice",
              "correct": false,
              "feedback": "Erreur : les coefficients nuls ne représentent aucune arête.\n"
            }
          ],
          "explanation": "Dans un graphe non orienté, la somme des coefficients de la matrice\nvaut deux fois le nombre d'arêtes."
        },
        {
          "statement": "La matrice d'adjacence d'un graphe non orienté à quatre sommets\ncontient $4$ coefficients égaux à $1$. Combien le graphe a-t-il\nd'arêtes ?",
          "options": [
            {
              "text": "$2$, chaque arête comptant deux fois",
              "correct": true,
              "feedback": "Bonne réponse : une arête entre $i$ et $j$ met un $1$ en\nposition $(i, j)$ et un autre en $(j, i)$ ; $4 / 2 = 2$.\n"
            },
            {
              "text": "$4$, un par coefficient égal à $1$",
              "correct": false,
              "feedback": "Erreur : la matrice est symétrique, chaque arête apparaît deux\nfois.\n"
            },
            {
              "text": "$8$, deux par coefficient égal à $1$",
              "correct": false,
              "feedback": "Erreur : c'est l'inverse, deux coefficients pour une arête.\n"
            },
            {
              "text": "$16$, un par coefficient de la matrice",
              "correct": false,
              "feedback": "Erreur : les coefficients nuls ne représentent aucune arête.\n"
            }
          ],
          "explanation": "Dans un graphe non orienté, la somme des coefficients de la matrice\nvaut deux fois le nombre d'arêtes."
        }
      ]
    },
    {
      "id": "q32",
      "difficulty": 1,
      "skills": [
        "representation",
        "matrice",
        "symetrie"
      ],
      "title": "Une matrice d'adjacence symétrique",
      "partie": "representation",
      "statement": "La matrice d'adjacence d'un graphe est symétrique, le coefficient\n$(i, j)$ étant toujours égal au coefficient $(j, i)$. Que\ntraduit cette symétrie ?",
      "options": [
        {
          "text": "Le graphe est non orienté, à arêtes à double sens",
          "correct": true,
          "feedback": "Bonne réponse : si $i$ est relié à $j$, alors $j$ est relié à\n$i$ ; c'est la définition d'une arête non orientée.\n"
        },
        {
          "text": "Le graphe est connexe, tous les sommets étant reliés",
          "correct": false,
          "feedback": "Erreur : la symétrie ne dit rien sur l'existence de chemins\nentre les sommets.\n"
        },
        {
          "text": "Tous les sommets ont le même degré, le graphe étant régulier",
          "correct": false,
          "feedback": "Erreur : la symétrie n'égalise pas les lignes entre elles.\n"
        },
        {
          "text": "Le graphe contient au moins un cycle passant par chaque sommet",
          "correct": false,
          "feedback": "Erreur : un arbre a une matrice symétrique et aucun cycle.\n"
        }
      ],
      "explanation": "Orienté ou non, cela se lit sur la matrice : symétrique pour un\ngraphe non orienté, quelconque pour un graphe orienté."
    },
    {
      "id": "q33",
      "difficulty": 2,
      "skills": [
        "representation",
        "matrice",
        "boucle"
      ],
      "title": "Un coefficient sur la diagonale",
      "partie": "representation",
      "statement": "Dans une matrice d'adjacence, le coefficient $(2, 2)$ vaut $1$.\nQue représente-t-il ?",
      "options": [
        {
          "text": "Une boucle, arête du sommet $2$ vers lui-même",
          "correct": true,
          "feedback": "Bonne réponse : la ligne et la colonne désignent le même\nsommet ; l'arête part de $2$ et arrive en $2$. Un graphe simple\nn'en contient pas, mais un graphe quelconque peut en avoir.\n"
        },
        {
          "text": "Une erreur, la diagonale étant forcément nulle",
          "correct": false,
          "feedback": "Erreur : la diagonale est nulle dans un graphe simple, pas\ndans un graphe quelconque.\n"
        },
        {
          "text": "Un sommet isolé, sans aucun voisin",
          "correct": false,
          "feedback": "Erreur : un sommet isolé a une ligne entièrement nulle.\n"
        },
        {
          "text": "Un sommet relié à tous les autres",
          "correct": false,
          "feedback": "Erreur : ce serait une ligne entière de $1$, hors diagonale.\n"
        }
      ],
      "explanation": "Ligne $i$, colonne $j$ : une arête de $i$ vers $j$. Sur la\ndiagonale, départ et arrivée coïncident."
    },
    {
      "id": "q34",
      "difficulty": 3,
      "skills": [
        "representation",
        "liste-adjacence",
        "aretes",
        "calcul"
      ],
      "title": "Compter les arêtes dans une liste d'adjacence",
      "partie": "representation",
      "statement": "Un graphe non orienté est représenté par ce dictionnaire des\nvoisins. Combien a-t-il d'arêtes ?\n```python\ng = {\"A\": [\"B\", \"C\"], \"B\": [\"A\"], \"C\": [\"A\", \"D\"], \"D\": [\"C\"]}\n```",
      "options": [
        {
          "text": "$3$, la moitié de la somme des longueurs",
          "correct": true,
          "feedback": "Bonne réponse : les listes totalisent $6$ voisins, et chaque\narête figure dans la liste de ses deux extrémités, d'où\n$6 / 2 = 3$.\n"
        },
        {
          "text": "$6$, la somme des longueurs des listes",
          "correct": false,
          "feedback": "Erreur : chaque arête est comptée deux fois, une par extrémité.\n"
        },
        {
          "text": "$4$, le nombre de listes, une par sommet",
          "correct": false,
          "feedback": "Erreur : le nombre de clés est le nombre de sommets, pas\nd'arêtes.\n"
        },
        {
          "text": "$12$, deux par voisin mentionné dans une liste",
          "correct": false,
          "feedback": "Erreur : c'est l'inverse, deux mentions pour une arête.\n"
        }
      ],
      "explanation": "La somme des degrés d'un graphe non orienté vaut deux fois le\nnombre d'arêtes, quelle que soit la représentation.",
      "variants": [
        {
          "statement": "Un graphe non orienté est représenté par ce dictionnaire des\nvoisins. Combien a-t-il d'arêtes ?\n```python\ng = {\"A\": [\"B\", \"C\"], \"B\": [\"A\"], \"C\": [\"A\", \"D\"], \"D\": [\"C\"]}\n```",
          "options": [
            {
              "text": "$3$, la moitié de la somme des longueurs",
              "correct": true,
              "feedback": "Bonne réponse : les listes totalisent $6$ voisins, et chaque\narête figure dans la liste de ses deux extrémités, d'où\n$6 / 2 = 3$.\n"
            },
            {
              "text": "$6$, la somme des longueurs des listes",
              "correct": false,
              "feedback": "Erreur : chaque arête est comptée deux fois, une par extrémité.\n"
            },
            {
              "text": "$4$, le nombre de listes, une par sommet",
              "correct": false,
              "feedback": "Erreur : le nombre de clés est le nombre de sommets, pas\nd'arêtes.\n"
            },
            {
              "text": "$12$, deux par voisin mentionné dans une liste",
              "correct": false,
              "feedback": "Erreur : c'est l'inverse, deux mentions pour une arête.\n"
            }
          ],
          "explanation": "La somme des degrés d'un graphe non orienté vaut deux fois le\nnombre d'arêtes, quelle que soit la représentation."
        },
        {
          "statement": "Un graphe non orienté est représenté par ce dictionnaire des\nvoisins. Combien a-t-il d'arêtes ?\n```python\ng = {\"A\": [\"B\", \"C\"], \"B\": [\"A\"], \"C\": [\"A\", \"D\", \"E\"], \"D\": [\"C\"], \"E\": [\"C\"]}\n```",
          "options": [
            {
              "text": "$4$, la moitié de la somme des longueurs",
              "correct": true,
              "feedback": "Bonne réponse : les listes totalisent $8$ voisins, et chaque\narête figure dans la liste de ses deux extrémités, d'où\n$8 / 2 = 4$.\n"
            },
            {
              "text": "$8$, la somme des longueurs des listes",
              "correct": false,
              "feedback": "Erreur : chaque arête est comptée deux fois, une par extrémité.\n"
            },
            {
              "text": "$5$, le nombre de listes, une par sommet",
              "correct": false,
              "feedback": "Erreur : le nombre de clés est le nombre de sommets, pas\nd'arêtes.\n"
            },
            {
              "text": "$16$, deux par voisin mentionné dans une liste",
              "correct": false,
              "feedback": "Erreur : c'est l'inverse, deux mentions pour une arête.\n"
            }
          ],
          "explanation": "La somme des degrés d'un graphe non orienté vaut deux fois le\nnombre d'arêtes, quelle que soit la représentation."
        },
        {
          "statement": "Un graphe non orienté est représenté par ce dictionnaire des\nvoisins. Combien a-t-il d'arêtes ?\n```python\ng = {\"A\": [\"B\"], \"B\": [\"A\", \"C\", \"D\"], \"C\": [\"B\"], \"D\": [\"B\", \"E\", \"F\"], \"E\": [\"D\"], \"F\": [\"D\"]}\n```",
          "options": [
            {
              "text": "$5$, la moitié de la somme des longueurs",
              "correct": true,
              "feedback": "Bonne réponse : les listes totalisent $10$ voisins, et chaque\narête figure dans la liste de ses deux extrémités, d'où\n$10 / 2 = 5$.\n"
            },
            {
              "text": "$10$, la somme des longueurs des listes",
              "correct": false,
              "feedback": "Erreur : chaque arête est comptée deux fois, une par extrémité.\n"
            },
            {
              "text": "$6$, le nombre de listes, une par sommet",
              "correct": false,
              "feedback": "Erreur : le nombre de clés est le nombre de sommets, pas\nd'arêtes.\n"
            },
            {
              "text": "$20$, deux par voisin mentionné dans une liste",
              "correct": false,
              "feedback": "Erreur : c'est l'inverse, deux mentions pour une arête.\n"
            }
          ],
          "explanation": "La somme des degrés d'un graphe non orienté vaut deux fois le\nnombre d'arêtes, quelle que soit la représentation."
        }
      ]
    },
    {
      "id": "q35",
      "difficulty": 2,
      "skills": [
        "representation",
        "liste-adjacence",
        "oriente"
      ],
      "title": "Un arc dans une liste d'adjacence",
      "partie": "representation",
      "statement": "Un graphe orienté possède un arc de `A` vers `B`, et aucun de `B`\nvers `A`. Où cet arc apparaît-il dans le dictionnaire des\nsuccesseurs ?",
      "options": [
        {
          "text": "Dans la liste de `A` seulement, qui contient `B`",
          "correct": true,
          "feedback": "Bonne réponse : la liste d'un sommet donne ses successeurs ;\n`B` est successeur de `A`, mais `A` n'est pas successeur de\n`B`.\n"
        },
        {
          "text": "Dans les listes de `A` et de `B`, comme toute arête",
          "correct": false,
          "feedback": "Erreur : la double mention vaut pour les graphes non orientés.\n"
        },
        {
          "text": "Dans la liste de `B` seulement, qui contient `A`",
          "correct": false,
          "feedback": "Erreur : ce serait un arc de `B` vers `A`.\n"
        },
        {
          "text": "Dans une liste à part, les arcs ne se rangeant pas par sommet",
          "correct": false,
          "feedback": "Erreur : la liste d'adjacence range bien les arcs par sommet\nde départ.\n"
        }
      ],
      "explanation": "Dans un graphe orienté, la liste d'adjacence d'un sommet est la\nliste de ses successeurs : l'arc n'est écrit qu'au départ."
    },
    {
      "id": "q36",
      "difficulty": 2,
      "skills": [
        "modelisation",
        "oriente",
        "taches"
      ],
      "title": "Modéliser des tâches qui s'enchaînent",
      "partie": "modelisation",
      "statement": "Un projet comporte des tâches dont certaines doivent être finies\navant que d'autres commencent. Quel graphe modélise ces\ncontraintes ?",
      "options": [
        {
          "text": "Un graphe orienté, un arc allant d'une tâche à celle qui doit la suivre",
          "correct": true,
          "feedback": "Bonne réponse : la contrainte « avant » a un sens, l'arc aussi.\nUn cycle dans ce graphe signalerait des contraintes\nimpossibles à satisfaire.\n"
        },
        {
          "text": "Un graphe non orienté, l'ordre des tâches n'ayant pas d'importance",
          "correct": false,
          "feedback": "Erreur : l'ordre est précisément ce que l'on veut représenter.\n"
        },
        {
          "text": "Un arbre binaire, chaque tâche ayant au plus deux suivantes",
          "correct": false,
          "feedback": "Erreur : rien ne limite le nombre de tâches suivantes ni\nprécédentes.\n"
        },
        {
          "text": "Une simple liste, les tâches s'exécutant toujours en séquence",
          "correct": false,
          "feedback": "Erreur : deux tâches sans contrainte entre elles peuvent être\nmenées en parallèle, une liste ne le dit pas.\n"
        }
      ],
      "explanation": "Choisir orienté ou non revient à se demander si la relation a un\nsens : « doit précéder » en a un."
    },
    {
      "id": "q37",
      "difficulty": 2,
      "skills": [
        "modelisation",
        "aretes",
        "maximum",
        "calcul"
      ],
      "title": "Le nombre maximal d'arêtes d'un graphe simple",
      "partie": "modelisation",
      "statement": "Un graphe simple non orienté, sans boucle ni arête double, a\n$5$ sommets. Combien d'arêtes peut-il avoir au maximum ?",
      "options": [
        {
          "text": "$10$, une par paire de sommets",
          "correct": true,
          "feedback": "Bonne réponse : chaque sommet peut être relié aux $4$\nautres, et chaque arête relie deux sommets, d'où\n$5 \\times 4 / 2 = 10$.\n"
        },
        {
          "text": "$5$, une par sommet",
          "correct": false,
          "feedback": "Erreur : un sommet peut avoir bien plus d'une arête.\n"
        },
        {
          "text": "$25$, une par case de la matrice",
          "correct": false,
          "feedback": "Erreur : la diagonale est exclue et chaque arête occupe deux\ncases.\n"
        },
        {
          "text": "$20$, une par couple ordonné",
          "correct": false,
          "feedback": "Erreur : l'arête de $i$ à $j$ est la même que celle de $j$ à\n$i$.\n"
        }
      ],
      "explanation": "Le graphe complet à $n$ sommets a $n(n-1)/2$ arêtes : c'est la\nborne qui rend la matrice d'adjacence rentable quand le graphe est\ndense.",
      "variants": [
        {
          "statement": "Un graphe simple non orienté, sans boucle ni arête double, a\n$5$ sommets. Combien d'arêtes peut-il avoir au maximum ?",
          "options": [
            {
              "text": "$10$, une par paire de sommets",
              "correct": true,
              "feedback": "Bonne réponse : chaque sommet peut être relié aux $4$\nautres, et chaque arête relie deux sommets, d'où\n$5 \\times 4 / 2 = 10$.\n"
            },
            {
              "text": "$5$, une par sommet",
              "correct": false,
              "feedback": "Erreur : un sommet peut avoir bien plus d'une arête.\n"
            },
            {
              "text": "$25$, une par case de la matrice",
              "correct": false,
              "feedback": "Erreur : la diagonale est exclue et chaque arête occupe deux\ncases.\n"
            },
            {
              "text": "$20$, une par couple ordonné",
              "correct": false,
              "feedback": "Erreur : l'arête de $i$ à $j$ est la même que celle de $j$ à\n$i$.\n"
            }
          ],
          "explanation": "Le graphe complet à $n$ sommets a $n(n-1)/2$ arêtes : c'est la\nborne qui rend la matrice d'adjacence rentable quand le graphe est\ndense."
        },
        {
          "statement": "Un graphe simple non orienté, sans boucle ni arête double, a\n$6$ sommets. Combien d'arêtes peut-il avoir au maximum ?",
          "options": [
            {
              "text": "$15$, une par paire de sommets",
              "correct": true,
              "feedback": "Bonne réponse : chaque sommet peut être relié aux $5$\nautres, et chaque arête relie deux sommets, d'où\n$6 \\times 5 / 2 = 15$.\n"
            },
            {
              "text": "$6$, une par sommet",
              "correct": false,
              "feedback": "Erreur : un sommet peut avoir bien plus d'une arête.\n"
            },
            {
              "text": "$36$, une par case de la matrice",
              "correct": false,
              "feedback": "Erreur : la diagonale est exclue et chaque arête occupe deux\ncases.\n"
            },
            {
              "text": "$30$, une par couple ordonné",
              "correct": false,
              "feedback": "Erreur : l'arête de $i$ à $j$ est la même que celle de $j$ à\n$i$.\n"
            }
          ],
          "explanation": "Le graphe complet à $n$ sommets a $n(n-1)/2$ arêtes : c'est la\nborne qui rend la matrice d'adjacence rentable quand le graphe est\ndense."
        },
        {
          "statement": "Un graphe simple non orienté, sans boucle ni arête double, a\n$8$ sommets. Combien d'arêtes peut-il avoir au maximum ?",
          "options": [
            {
              "text": "$28$, une par paire de sommets",
              "correct": true,
              "feedback": "Bonne réponse : chaque sommet peut être relié aux $7$\nautres, et chaque arête relie deux sommets, d'où\n$8 \\times 7 / 2 = 28$.\n"
            },
            {
              "text": "$8$, une par sommet",
              "correct": false,
              "feedback": "Erreur : un sommet peut avoir bien plus d'une arête.\n"
            },
            {
              "text": "$64$, une par case de la matrice",
              "correct": false,
              "feedback": "Erreur : la diagonale est exclue et chaque arête occupe deux\ncases.\n"
            },
            {
              "text": "$56$, une par couple ordonné",
              "correct": false,
              "feedback": "Erreur : l'arête de $i$ à $j$ est la même que celle de $j$ à\n$i$.\n"
            }
          ],
          "explanation": "Le graphe complet à $n$ sommets a $n(n-1)/2$ arêtes : c'est la\nborne qui rend la matrice d'adjacence rentable quand le graphe est\ndense."
        }
      ]
    },
    {
      "id": "q38",
      "difficulty": 3,
      "skills": [
        "parcours",
        "cycle",
        "profondeur",
        "detection"
      ],
      "title": "Détecter un cycle pendant un parcours en profondeur",
      "partie": "parcours",
      "statement": "Lors d'un parcours en profondeur d'un graphe non orienté, à quel\nsigne reconnaît-on la présence d'un cycle ?",
      "options": [
        {
          "text": "On retombe sur un sommet déjà visité, autre que le précédent",
          "correct": true,
          "feedback": "Bonne réponse : il existe alors deux chemins distincts vers ce\nsommet, celui du parcours et l'arête que l'on vient d'emprunter.\nLe voisin d'où l'on vient est exclu, l'arête parcourue en sens\ninverse ne formant pas un cycle.\n"
        },
        {
          "text": "On revient au sommet de départ à la fin du parcours",
          "correct": false,
          "feedback": "Erreur : tout parcours en profondeur revient au départ en\ndépilant, cycle ou non.\n"
        },
        {
          "text": "On visite deux fois le même sommet, ce qui arrive dans tout graphe",
          "correct": false,
          "feedback": "Erreur : un sommet marqué n'est jamais visité deux fois ; ce\nqui compte, c'est de le rencontrer à nouveau.\n"
        },
        {
          "text": "On rencontre un sommet sans aucun voisin encore à visiter",
          "correct": false,
          "feedback": "Erreur : un sommet isolé n'appartient à aucun cycle.\n"
        }
      ],
      "explanation": "Un parcours en profondeur construit un arbre ; toute arête qui\nramène vers un sommet déjà dans l'arbre, hors le parent, ferme un\ncycle."
    },
    {
      "id": "q39",
      "difficulty": 2,
      "skills": [
        "parcours",
        "connexite",
        "composantes"
      ],
      "title": "Parcourir un graphe non connexe",
      "partie": "parcours",
      "statement": "Un graphe non orienté a $10$ sommets, $8$ arêtes et $3$\ncomposantes connexes. Combien de fois faut-il lancer un parcours\nen largeur, depuis un sommet non encore visité, pour visiter tous\nles sommets ?",
      "options": [
        {
          "text": "$3$ fois, une par composante",
          "correct": true,
          "feedback": "Bonne réponse : un parcours atteint exactement la composante de\nson sommet de départ ; il en faut un par composante, et compter\nces lancements compte les composantes.\n"
        },
        {
          "text": "$1$ fois, un parcours atteignant tous les sommets",
          "correct": false,
          "feedback": "Erreur : un parcours ne franchit pas les frontières entre\ncomposantes, faute d'arête.\n"
        },
        {
          "text": "$10$ fois, une par sommet",
          "correct": false,
          "feedback": "Erreur : les sommets déjà visités ne relancent rien.\n"
        },
        {
          "text": "$8$ fois, une par arête",
          "correct": false,
          "feedback": "Erreur : les arêtes sont suivies pendant le parcours, elles ne\nle relancent pas.\n"
        }
      ],
      "explanation": "Relancer un parcours sur chaque sommet non visité est la méthode\nstandard pour compter les composantes connexes.",
      "variants": [
        {
          "statement": "Un graphe non orienté a $10$ sommets, $8$ arêtes et $3$\ncomposantes connexes. Combien de fois faut-il lancer un parcours\nen largeur, depuis un sommet non encore visité, pour visiter tous\nles sommets ?",
          "options": [
            {
              "text": "$3$ fois, une par composante",
              "correct": true,
              "feedback": "Bonne réponse : un parcours atteint exactement la composante de\nson sommet de départ ; il en faut un par composante, et compter\nces lancements compte les composantes.\n"
            },
            {
              "text": "$1$ fois, un parcours atteignant tous les sommets",
              "correct": false,
              "feedback": "Erreur : un parcours ne franchit pas les frontières entre\ncomposantes, faute d'arête.\n"
            },
            {
              "text": "$10$ fois, une par sommet",
              "correct": false,
              "feedback": "Erreur : les sommets déjà visités ne relancent rien.\n"
            },
            {
              "text": "$8$ fois, une par arête",
              "correct": false,
              "feedback": "Erreur : les arêtes sont suivies pendant le parcours, elles ne\nle relancent pas.\n"
            }
          ],
          "explanation": "Relancer un parcours sur chaque sommet non visité est la méthode\nstandard pour compter les composantes connexes."
        },
        {
          "statement": "Un graphe non orienté a $7$ sommets, $6$ arêtes et $2$\ncomposantes connexes. Combien de fois faut-il lancer un parcours\nen largeur, depuis un sommet non encore visité, pour visiter tous\nles sommets ?",
          "options": [
            {
              "text": "$2$ fois, une par composante",
              "correct": true,
              "feedback": "Bonne réponse : un parcours atteint exactement la composante de\nson sommet de départ ; il en faut un par composante, et compter\nces lancements compte les composantes.\n"
            },
            {
              "text": "$1$ fois, un parcours atteignant tous les sommets",
              "correct": false,
              "feedback": "Erreur : un parcours ne franchit pas les frontières entre\ncomposantes, faute d'arête.\n"
            },
            {
              "text": "$7$ fois, une par sommet",
              "correct": false,
              "feedback": "Erreur : les sommets déjà visités ne relancent rien.\n"
            },
            {
              "text": "$6$ fois, une par arête",
              "correct": false,
              "feedback": "Erreur : les arêtes sont suivies pendant le parcours, elles ne\nle relancent pas.\n"
            }
          ],
          "explanation": "Relancer un parcours sur chaque sommet non visité est la méthode\nstandard pour compter les composantes connexes."
        },
        {
          "statement": "Un graphe non orienté a $12$ sommets, $9$ arêtes et $4$\ncomposantes connexes. Combien de fois faut-il lancer un parcours\nen largeur, depuis un sommet non encore visité, pour visiter tous\nles sommets ?",
          "options": [
            {
              "text": "$4$ fois, une par composante",
              "correct": true,
              "feedback": "Bonne réponse : un parcours atteint exactement la composante de\nson sommet de départ ; il en faut un par composante, et compter\nces lancements compte les composantes.\n"
            },
            {
              "text": "$1$ fois, un parcours atteignant tous les sommets",
              "correct": false,
              "feedback": "Erreur : un parcours ne franchit pas les frontières entre\ncomposantes, faute d'arête.\n"
            },
            {
              "text": "$12$ fois, une par sommet",
              "correct": false,
              "feedback": "Erreur : les sommets déjà visités ne relancent rien.\n"
            },
            {
              "text": "$9$ fois, une par arête",
              "correct": false,
              "feedback": "Erreur : les arêtes sont suivies pendant le parcours, elles ne\nle relancent pas.\n"
            }
          ],
          "explanation": "Relancer un parcours sur chaque sommet non visité est la méthode\nstandard pour compter les composantes connexes."
        }
      ]
    }
  ]
}