38. Grafos hamiltonianos

Un camino hamiltoniano visita todos los vértices exactamente una vez. Si además regresa al punto inicial, forma un ciclo hamiltoniano y el grafo se denomina hamiltoniano.

38.1 Introducción

Los problemas hamiltonianos preguntan si es posible recorrer todos los lugares sin repetir ninguno. A diferencia de los caminos mínimos, aquí importa cubrir el conjunto completo de vértices.

Esta estructura aparece en planificación, secuenciación, rompecabezas y en el problema del viajante estudiado anteriormente.

38.2 Camino hamiltoniano

Un camino hamiltoniano contiene todos los vértices del grafo exactamente una vez. No necesita terminar donde comenzó.

v₁ → v₂ → ... → vₙ, con cada vértice de V presente una sola vez

Puede haber muchos caminos hamiltonianos, uno solo o ninguno.

38.3 Ciclo hamiltoniano

Un ciclo hamiltoniano visita todos los vértices exactamente una vez y contiene una arista que une el último con el primero.

v₁ → v₂ → ... → vₙ → v₁

Un grafo es hamiltoniano si contiene al menos uno de estos ciclos.

38.4 Camino y ciclo no son equivalentes

Todo ciclo hamiltoniano produce un camino hamiltoniano al quitar una arista. La implicación inversa no siempre se cumple.

Por ejemplo, un camino simple con varios vértices es hamiltoniano como camino, pero no contiene ninguna arista que permita regresar del extremo final al inicial.

38.5 Condiciones necesarias básicas

Si un grafo posee un ciclo hamiltoniano, debe ser conectado y cada vértice debe tener grado al menos 2.

Hamiltoniano ⇒ conectado y δ(G) ≥ 2

Estas condiciones permiten descartar casos, pero no garantizan un ciclo: existen grafos conectados de grado mínimo 2 que no son hamiltonianos.

38.6 Simulación con backtracking

Avanza por la búsqueda. La rama A–B–D–E–C termina sin poder completar el ciclo; el algoritmo retrocede y prueba E–F hasta encontrar una solución.

Camino parcial

Vértices disponibles

A, B, C, D, E, F, G

Acción actual

Comenzar en A.
Búsqueda preparada.
Paso0 / 10
Vértices en camino0 / 7
Retrocesos0
ResultadoBuscando

38.7 Vértices de corte

Un grafo hamiltoniano con al menos tres vértices no puede tener un vértice de corte. Si se elimina cualquier vértice de su ciclo hamiltoniano, los restantes todavía quedan conectados mediante un camino.

Existe un vértice de corte ⇒ no existe ciclo hamiltoniano

38.8 Condición sobre subconjuntos

Si G es hamiltoniano, al eliminar un conjunto S de vértices no pueden quedar más de |S| componentes.

Para todo S ≠ ∅: componentes(G − S) ≤ |S|

También es una condición necesaria, no una caracterización completa.

38.9 Teorema de Dirac

Sea G un grafo simple con n ≥ 3 vértices. Si cada vértice tiene grado al menos n/2, entonces G es hamiltoniano.

δ(G) ≥ n/2 ⇒ G es hamiltoniano

Dirac proporciona una condición suficiente. Un grafo que no la cumple todavía puede ser hamiltoniano.

38.10 Teorema de Ore

Sea G simple con n ≥ 3. Si para cada par de vértices no adyacentes u y v se cumple grado(u) + grado(v) ≥ n, entonces G es hamiltoniano.

u no adyacente a v ⇒ grado(u) + grado(v) ≥ n

Ore generaliza la intuición de que una densidad alta fuerza la existencia de un ciclo global.

38.11 Condiciones suficientes y necesarias

PruebaSi se cumpleSi no se cumple
Grado mínimo 2Solo permite continuarNo es hamiltoniano
Sin vértice de corteSolo permite continuarNo es hamiltoniano
DiracEs hamiltonianoNo concluye
OreEs hamiltonianoNo concluye

38.12 Búsqueda mediante backtracking

Se fija un origen y se construye un camino. Cada candidato debe ser vecino del último vértice y no haber sido visitado. Si se incluyen todos, se comprueba el regreso al origen.

function buscar(posicion) {
  if (posicion === vertices.length) {
    return sonAdyacentes(camino[posicion - 1], camino[0]);
  }

  for (const candidato of vecinos[camino[posicion - 1]]) {
    if (!visitado.has(candidato)) {
      camino[posicion] = candidato;
      visitado.add(candidato);
      if (buscar(posicion + 1)) return true;
      visitado.delete(candidato);
    }
  }
  return false;
}

38.13 Implementación completa

function cicloHamiltoniano(grafo) {
  const vertices = Object.keys(grafo);
  if (vertices.length === 0) return null;
  const camino = [vertices[0]];
  const visitado = new Set(camino);

  function dfs() {
    if (camino.length === vertices.length) {
      return grafo[camino.at(-1)].includes(camino[0]);
    }
    for (const vecino of grafo[camino.at(-1)]) {
      if (!visitado.has(vecino)) {
        visitado.add(vecino); camino.push(vecino);
        if (dfs()) return true;
        camino.pop(); visitado.delete(vecino);
      }
    }
    return false;
  }
  return dfs() ? [...camino, camino[0]] : null;
}

38.14 Poda de la búsqueda

El backtracking mejora si abandona estados que aíslan vértices no visitados, crean un extremo sin salida o dividen el resto del grafo en componentes incompatibles.

Ordenar primero los candidatos más restrictivos puede descubrir antes los fracasos y reducir notablemente el árbol de búsqueda.

38.15 Programación dinámica por subconjuntos

Puede almacenarse si existe un camino que comienza en un origen, visita exactamente el subconjunto S y termina en v.

DP[S][v] = existe un camino desde s hasta v que visita exactamente S

El método usa O(n²2ⁿ) tiempo y O(n2ⁿ) espacio: sigue siendo exponencial, pero evita repetir subproblemas.

38.16 Complejidad

Decidir si un grafo contiene un ciclo hamiltoniano es NP-completo. Una búsqueda directa puede explorar O(n!) órdenes de vértices.

Verificar un ciclo propuesto cuesta solo O(n), pero encontrarlo o demostrar que no existe puede requerir tiempo exponencial.

38.17 Hamiltoniano frente a euleriano

ConceptoDebe recorrerRepeticionesCriterio
HamiltonianoTodos los vérticesNo repite vérticesNo existe caracterización simple conocida
EulerianoTodas las aristasPuede repetir vérticesSe decide mediante grados y conectividad

38.18 Aplicaciones y errores comunes

  • Planificar visitas sin repetir ubicaciones.
  • Secuenciar operaciones o configuraciones.
  • Resolver rompecabezas de recorrido.
  • Confundir visitar vértices con recorrer aristas.
  • Creer que grado mínimo 2 garantiza un ciclo.
  • Aceptar un camino sin comprobar la arista de regreso.
  • No desmarcar el vértice al retroceder.
  • Interpretar el fallo de una heurística como prueba de inexistencia.

38.19 Qué debes recordar de este tema

  • Un camino hamiltoniano visita cada vértice una vez.
  • Un ciclo hamiltoniano también regresa al inicio.
  • Conectividad y grado mínimo 2 son condiciones necesarias.
  • Dirac y Ore proporcionan condiciones suficientes.
  • Backtracking explora elecciones y revierte las que fracasan.
  • El problema del ciclo hamiltoniano es NP-completo.
  • TSP busca el ciclo hamiltoniano de menor costo.

38.20 Conclusión

La hamiltonicidad exige una estructura global que no puede deducirse únicamente mirando grados locales. Las condiciones teóricas resuelven algunos casos y la búsqueda exacta cubre los restantes a costa de complejidad exponencial.

En el próximo tema estudiaremos grafos eulerianos, donde el objetivo cambia de visitar vértices a recorrer todas las aristas.