Exercice 2 : Graphes bipartis et flot
Problème guidé : Couplages maximaux et flots dans les réseaux
Section titled “Problème guidé : Couplages maximaux et flots dans les réseaux”En tant qu’examinateur de concours CPGE (filière MPI), ce problème vise à évaluer votre capacité à modéliser un problème combinatoire complexe à l’aide de la théorie des graphes, et plus particulièrement via la notion de flot maximal. Les concepts abordés (réductions, réseaux de transport, algorithme de Ford-Fulkerson / Edmonds-Karp) sont centraux aux épreuves écrites d’informatique (X, ENS, Mines-Ponts, Centrale-Supélec).
1. Introduction et Rapports de modélisation
Section titled “1. Introduction et Rapports de modélisation”Soit un graphe non orienté. Un couplage (ou appariement) dans est un sous-ensemble d’arêtes tel que deux arêtes distinctes de ne partagent aucune extrémité commune. Un couplage est dit maximal (en cardinalité) s’il n’existe aucun autre couplage de cardinal strictement supérieur.
Le graphe est dit bipartis si son ensemble de sommets peut être partitionné en deux sous-ensembles disjoints et tels que toute arête de a une extrémité dans et l’autre dans . On note alors .
Question préliminaire (Modélisation)
Section titled “Question préliminaire (Modélisation)”Soit un graphe bipartis. Décrivez comment transformer la recherche d’un couplage maximal dans en un problème de flot maximal dans un réseau de transport orienté . Précisez l’ensemble des sommets , les arêtes orientées ainsi que leur capacité .
2. Correction pas à pas
Section titled “2. Correction pas à pas”1. Modélisation par un réseau de flot
Section titled “1. Modélisation par un réseau de flot”Pour ramener le problème du couplage maximal à un problème de flot, on construit un réseau orienté de la manière suivante :
-
Ensemble des sommets : On ajoute au graphe initial une source et un puits . Ainsi :
-
Ensemble des arêtes orientées et capacités :
- Pour chaque arête avec et , on trace une arête orientée de vers : , avec une capacité (ou , puisque chaque sommet ne peut être saturé qu’une fois).
- Pour chaque sommet , on ajoute une arête orientée de la source vers : avec .
- Pour chaque sommet , on ajoute une arête orientée de vers le puits : avec .
2. Justification mathématique (Théorème de Ford-Fulkerson et Flot Entier)
Section titled “2. Justification mathématique (Théorème de Ford-Fulkerson et Flot Entier)”Puisque toutes les capacités sur les arêtes , et sont des entiers (ou ), le théorème des flots entiers garantit que l’algorithme de Ford-Fulkerson (ou son raffinement Edmonds-Karp) trouvera un flot maximal entier (valeurs 0 ou 1 sur chaque arête).
- Correspondance : Les arêtes du graphe bipartis qui portent un flot de valeur dans le réseau forment exactement un couplage .
- Optimalité : Par le théorème flots-coupes (Max-Flow Min-Cut), la valeur du flot maximal dans est égale à la capacité de la coupe minimale, ce qui correspond exactement au cardinal du couplage maximal dans (et par le théorème de König, à la taille de la couverture minimale par sommets).
3. Implémentation en Python
Section titled “3. Implémentation en Python”Voici une implémentation académique propre utilisant l’algorithme de Ford-Fulkerson (via DFS) pour résoudre le problème du couplage maximal dans un graphe bipartis.
def dfs_flot(u, t, f_val, visited, graph, capacities, flow): if u == t: return f_val visited.add(u) for v in graph[u]: residual = capacities[(u, v)] - flow[(u, v)] if v not in visited and residual > 0: push = dfs_flot(v, t, min(f_val, residual), visited, graph, capacities, flow) if push > 0: flow[(u, v)] += push flow[(v, u)] -= push return push return 0
def hopcroft_karp_or_ford_fulkerson(X, Y, E): """ Calcule un couplage maximal dans un graphe bipartis G = (X, Y, E) via la réduction au flot maximal. """ graph = {s: [] for s in X.union(Y).union({'s', 't'})} capacities = {e: 0 for e in [((u,v)) for u in graph for v in graph]} # Initialisation flow = {e: 0 for e in capacities}
# Construction du réseau for x in X: graph['s'].append(x) graph[x].append('s') capacities[('s', x)] = 1
for y in Y: graph[y].append('t') graph['t'].append(y) capacities[(y, 't')] = 1
for x, y in E: graph[x].append(y) graph[y].append(x) capacities[(x, y)] = 1 # Capacité unitaire suffit pour un couplage
# Algorithme de Ford-Fulkerson max_flow = 0 while True: visited = set() push = dfs_flot('s', 't', float('inf'), visited, graph, capacities, flow) if push == 0: break max_flow += push
# Extraction du couplage matching = [] for x in X: for y in graph[x]: if y in Y and flow[(x, y)] == 1: matching.append((x, y))
matching_size = max_flow return matching_size, matching4. Analyse critique et complexité
Section titled “4. Analyse critique et complexité”-
Complexité temporelle :
- Soit le nombre de sommets et le nombre d’arêtes.
- Le nombre maximal de flots augmentants est borné par le cardinal du couplage maximal, soit .
- Chaque recherche de chemin augmentant par DFS prend .
- La complexité totale de cette approche naïve est donc en .
- Remarque de concours : Pour des graphes bipartis denses, l’algorithme de Hopcroft-Karp offre une meilleure complexité en , attendue dans les problèmes plus ardus des concours ENS.
-
Limites de la modélisation par flot général : Bien que robuste, utiliser un algorithme de flot général (Ford-Fulkerson) pour un simple couplage bipartis peut s’avérer sur-dimensionné si l’on ne restreint pas l’utilisation des structures de données. L’utilisation de chemins augmentants directs (comme dans l’algorithme de Hopcroft-Karp ou de匈牙利 / Kuhn) exploite directement la structure bipartie sans manipuler explicitement les capacités résiduelles, réduisant ainsi les constantes cachées en mémoire et en temps d’exécution.