Introducción
El emparejamiento en grafos es un tema fundamental en la teoría de grafos y tiene aplicaciones en diversas áreas como la asignación de tareas, la planificación de horarios y la optimización de recursos. En este módulo, exploraremos los conceptos básicos, algoritmos y aplicaciones del emparejamiento en grafos.
Conceptos Básicos
Definiciones Clave
- Grafo Bipartito: Un grafo \( G = (V, E) \) es bipartito si sus vértices pueden dividirse en dos conjuntos disjuntos \( U \) y \( V \) tales que cada arista conecta un vértice en \( U \) con un vértice en \( V \).
- Emparejamiento: Un emparejamiento \( M \) en un grafo es un subconjunto de aristas \( E \) tal que no comparten vértices comunes.
- Emparejamiento Máximo: Un emparejamiento es máximo si no se puede agregar más aristas sin violar la propiedad de emparejamiento.
- Emparejamiento Perfecto: Un emparejamiento es perfecto si todos los vértices del grafo están emparejados.
Ejemplo de Grafo Bipartito
Consideremos un grafo bipartito \( G \) con conjuntos de vértices \( U = {u1, u2, u3} \) y \( V = {v1, v2, v3} \):
Algoritmos de Emparejamiento
Algoritmo de Emparejamiento de Hopcroft-Karp
El algoritmo de Hopcroft-Karp es uno de los algoritmos más eficientes para encontrar un emparejamiento máximo en un grafo bipartito. Funciona en tiempo \( O(\sqrt{V}E) \).
Pasos del Algoritmo
- Inicialización: Comenzar con un emparejamiento vacío.
- Búsqueda de Camino Aumentante: Utilizar una búsqueda en anchura (BFS) para encontrar un camino aumentante.
- Aumentar el Emparejamiento: Utilizar una búsqueda en profundidad (DFS) para aumentar el emparejamiento a lo largo del camino encontrado.
- Repetir: Repetir los pasos 2 y 3 hasta que no se puedan encontrar más caminos aumentantes.
Implementación en Python
from collections import deque def bfs(U, V, pair_U, pair_V, dist): queue = deque() for u in U: if pair_U[u] == None: dist[u] = 0 queue.append(u) else: dist[u] = float('inf') dist[None] = float('inf') while queue: u = queue.popleft() if dist[u] < dist[None]: for v in U[u]: if dist[pair_V[v]] == float('inf'): dist[pair_V[v]] = dist[u] + 1 queue.append(pair_V[v]) return dist[None] != float('inf') def dfs(u, U, V, pair_U, pair_V, dist): if u != None: for v in U[u]: if dist[pair_V[v]] == dist[u] + 1: if dfs(pair_V[v], U, V, pair_U, pair_V, dist): pair_V[v] = u pair_U[u] = v return True dist[u] = float('inf') return False return True def hopcroft_karp(U, V): pair_U = {u: None for u in U} pair_V = {v: None for v in V} dist = {} matching = 0 while bfs(U, V, pair_U, pair_V, dist): for u in U: if pair_U[u] == None: if dfs(u, U, V, pair_U, pair_V, dist): matching += 1 return matching, pair_U, pair_V # Ejemplo de uso U = { 'u1': ['v1', 'v2'], 'u2': ['v2', 'v3'], 'u3': ['v3'] } V = { 'v1': ['u1'], 'v2': ['u1', 'u2'], 'v3': ['u2', 'u3'] } matching, pair_U, pair_V = hopcroft_karp(U, V) print("Emparejamiento máximo:", matching) print("Emparejamiento de U:", pair_U) print("Emparejamiento de V:", pair_V)
Ejercicio Práctico
Ejercicio 1:
Dado el siguiente grafo bipartito, encuentra el emparejamiento máximo utilizando el algoritmo de Hopcroft-Karp:
U = { 'u1': ['v1', 'v2'], 'u2': ['v2', 'v3'], 'u3': ['v3', 'v4'], 'u4': ['v1', 'v4'] } V = { 'v1': ['u1', 'u4'], 'v2': ['u1', 'u2'], 'v3': ['u2', 'u3'], 'v4': ['u3', 'u4'] }
Solución:
U = { 'u1': ['v1', 'v2'], 'u2': ['v2', 'v3'], 'u3': ['v3', 'v4'], 'u4': ['v1', 'v4'] } V = { 'v1': ['u1', 'u4'], 'v2': ['u1', 'u2'], 'v3': ['u2', 'u3'], 'v4': ['u3', 'u4'] } matching, pair_U, pair_V = hopcroft_karp(U, V) print("Emparejamiento máximo:", matching) print("Emparejamiento de U:", pair_U) print("Emparejamiento de V:", pair_V)
Resumen
En esta sección, hemos cubierto los conceptos básicos del emparejamiento en grafos, incluyendo definiciones clave y ejemplos. También hemos explorado el algoritmo de Hopcroft-Karp para encontrar emparejamientos máximos en grafos bipartitos, proporcionando una implementación en Python y un ejercicio práctico para reforzar el aprendizaje. En la siguiente sección, profundizaremos en otros algoritmos de grafos y sus aplicaciones.
Algoritmos Avanzados
Módulo 1: Introducción a los Algoritmos Avanzados
Módulo 2: Algoritmos de Optimización
- Programación Lineal
- Algoritmos de Optimización Combinatoria
- Algoritmos Genéticos
- Optimización de Colonia de Hormigas
Módulo 3: Algoritmos en Grafos
- Representación de Grafos
- Búsqueda en Grafos: BFS y DFS
- Algoritmos de Caminos Mínimos
- Algoritmos de Flujo Máximo
- Algoritmos de Emparejamiento en Grafos
Módulo 4: Algoritmos de Búsqueda y Ordenación
Módulo 5: Algoritmos de Aprendizaje Automático
- Introducción al Aprendizaje Automático
- Algoritmos de Clasificación
- Algoritmos de Regresión
- Redes Neuronales y Deep Learning
- Algoritmos de Clustering
Módulo 6: Casos de Estudio y Aplicaciones
- Optimización en la Industria
- Aplicaciones de Grafos en Redes Sociales
- Búsqueda y Ordenación en Grandes Volúmenes de Datos
- Aplicaciones de Aprendizaje Automático en la Vida Real