40. Caminos, ciclos y conectividad

Los caminos describen cómo desplazarse por un grafo, los ciclos revelan retornos y dependencias circulares, y la conectividad indica si los vértices pueden comunicarse. Estas ideas fundamentan navegación, redes y planificación.

40.1 Introducción

Una vez definido un grafo, las preguntas naturales son: ¿puedo llegar de un vértice a otro?, ¿cuál es la ruta más corta?, ¿hay una vuelta que regresa al origen?, ¿la red está formada por una sola pieza?

Los conceptos de camino, ciclo y conectividad responden a estas preguntas. Aunque nacen en la teoría de grafos, aparecen en ruteo, dependencias de software, redes de comunicación y estructuras de control.

40.2 Recorridos y caminos

Un recorrido o paseo es una secuencia de vértices consecutivos unidos por aristas. Puede repetir vértices o aristas. Un camino simple es un recorrido que no repite vértices.

A, B, C, B, D es un recorrido si existen AB, BC, CB y BD.

A, B, C, D es un camino simple si los vértices son distintos.
La repetición permitida o no depende de la definición usada.

En muchos contextos informales se usa «camino» para cualquier recorrido. Al demostrar propiedades conviene especificar si se permite repetir vértices o aristas.

40.3 Longitud de un camino

La longitud de un camino sin pesos es la cantidad de aristas que recorre, no la cantidad de vértices.

Camino A → B → C → D.
Vértices visitados: 4.
Aristas recorridas: 3.

Longitud = 3.

En un grafo ponderado, una ruta puede tener además un costo que es la suma de los pesos de sus aristas. La longitud por cantidad de aristas y el costo ponderado son medidas diferentes.

40.4 Caminos en grafos dirigidos

En un digrafo, cada paso debe respetar la orientación de la arista. Tener una arista A → B no permite recorrer B → A salvo que exista esa arista inversa.

Aristas: A → B y B → C.

Existe un camino de A a C: A → B → C.
No existe necesariamente un camino de C a A.

Esta asimetría es esencial en dependencias, enlaces web y relaciones de seguimiento. La alcanzabilidad debe evaluarse con la dirección correcta.

40.5 Ciclos

Un ciclo es un camino cerrado que comienza y termina en el mismo vértice, sin repetir otros vértices en su versión simple. En un grafo no dirigido, un ciclo simple debe tener al menos tres vértices.

A → B → C → A es un ciclo de longitud 3.

En un árbol no hay ciclos.
Agregar una arista a un árbol crea un ciclo único.

Los ciclos pueden ser deseables, como rutas alternativas en una red, o problemáticos, como dependencias circulares entre módulos. El significado depende del dominio.

40.6 Ciclos en dependencias

Si una arista A → B significa «A necesita a B antes de ejecutarse», un ciclo indica una dependencia circular que bloquea el orden de ejecución.

A depende de B.
B depende de C.
C depende de A.

No existe una tarea que pueda comenzar sin esperar a otra del mismo ciclo.

Las herramientas de construcción de software, los gestores de paquetes y los planificadores detectan estos ciclos para informar una configuración imposible o exigir que se elimine una dependencia.

40.7 Grafos acíclicos dirigidos

Un grafo dirigido sin ciclos dirigidos se llama DAG, por directed acyclic graph. Los DAG son adecuados para modelar dependencias que siempre avanzan en una dirección.

Ejemplos de DAG:
prerrequisitos de materias;
tareas de compilación;
historial de versiones sin fusiones cíclicas;
etapas de un flujo de procesamiento.

Un DAG admite al menos un orden topológico: una lista de vértices donde cada arista u → v coloca a u antes que v. Los algoritmos para obtenerlo se estudiarán más adelante.

40.8 Conectividad en grafos no dirigidos

Un grafo no dirigido es conexo si existe un camino entre cada par de vértices. Si no lo es, sus partes conexas se llaman componentes conexas.

Componente 1: A—B—C.
Componente 2: D—E.

El grafo completo no es conexo;
tiene dos componentes conexas.

Cada componente conexa es una región máxima del grafo en la que todos los vértices pueden alcanzarse. No hay aristas que conecten una componente con otra.

40.9 Alcanzabilidad

Decimos que v es alcanzable desde u si existe un camino de u a v. En grafos no dirigidos, la alcanzabilidad es simétrica; en grafos dirigidos no tiene por qué serlo.

Grafo no dirigido: si A alcanza B, B alcanza A.

Digrafo: A → B no implica B → A.
La alcanzabilidad de un origen forma un conjunto de vértices visitables desde él.

La alcanzabilidad se puede calcular explorando vecinos. Los recorridos en profundidad y en anchura son las técnicas básicas para hacerlo.

40.10 Comprobar si existe un camino

function hayCamino(adyacentes, origen, destino) {
  const pendientes = [origen];
  const visitados = new Set([origen]);

  while (pendientes.length > 0) {
    const actual = pendientes.shift();
    if (actual === destino) return true;

    for (const vecino of adyacentes.get(actual) ?? []) {
      if (!visitados.has(vecino)) {
        visitados.add(vecino);
        pendientes.push(vecino);
      }
    }
  }
  return false;
}

const red = new Map([
  ["A", new Set(["B", "C"])],
  ["B", new Set(["D"])],
  ["C", new Set()],
  ["D", new Set()]
]);

console.log(hayCamino(red, "A", "D")); // true
console.log(hayCamino(red, "C", "D")); // false

El conjunto visitados evita recorrer una y otra vez los mismos vértices y permite que el algoritmo termine incluso si hay ciclos. El uso de una cola produce una exploración en anchura.

40.11 Componentes conexas

Para hallar todas las componentes de un grafo no dirigido, se inicia una exploración desde un vértice no visitado. Todos los vértices alcanzados forman una componente; luego se repite desde otro vértice pendiente.

1. Elegir un vértice no visitado.
2. Recorrer todos los alcanzables desde él.
3. Marcar ese conjunto como una componente.
4. Repetir hasta visitar todos los vértices.

La cantidad de exploraciones iniciadas es exactamente la cantidad de componentes. Esta técnica también ayuda a detectar islas de red o grupos separados de datos.

40.12 Implementar componentes conexas

function componentesConexas(adyacentes) {
  const visitados = new Set();
  const componentes = [];

  for (const inicio of adyacentes.keys()) {
    if (visitados.has(inicio)) continue;

    const componente = [];
    const pendientes = [inicio];
    visitados.add(inicio);

    while (pendientes.length > 0) {
      const actual = pendientes.pop();
      componente.push(actual);
      for (const vecino of adyacentes.get(actual) ?? []) {
        if (!visitados.has(vecino)) {
          visitados.add(vecino);
          pendientes.push(vecino);
        }
      }
    }
    componentes.push(componente);
  }
  return componentes;
}

La implementación usa una pila, por lo que explora en profundidad. En un grafo no dirigido, la lista de adyacencia debe contener ambos sentidos de cada arista y una clave para cada vértice aislado para que las componentes se calculen correctamente.

40.13 Conectividad fuerte y débil

Un digrafo es fuertemente conexo si para cualquier par u y v hay un camino de u a v y otro de v a u. Es débilmente conexo si al ignorar las direcciones, el grafo resultante es conexo.

A → B → C:
es débilmente conexo.
no es fuertemente conexo, porque C no alcanza A.

A → B → C → A sí es fuertemente conexo.

La conectividad fuerte representa comunicación bidireccional posible mediante rutas, aunque no exista una arista directa en ambos sentidos.

40.14 Distancia entre vértices

En un grafo no ponderado, la distancia d(u, v) es la longitud del camino más corto entre u y v. Si no existe camino, la distancia se considera infinita o no definida según la convención.

Si el camino más corto de A a D es A—B—D:
d(A, D) = 2.

La búsqueda en anchura encuentra distancias mínimas en cantidad de aristas en grafos no ponderados.

En grafos ponderados, la ruta con menos aristas puede no ser la de menor costo. Allí se requieren algoritmos que tomen en cuenta los pesos.

40.15 Excentricidad, radio y diámetro

En un grafo conexo, la excentricidad de un vértice es su máxima distancia a otro vértice. El radio es la menor excentricidad y el diámetro es la mayor.

Excentricidad de v: la distancia más lejana desde v.
Radio: mejor máximo posible.
Diámetro: mayor distancia mínima entre dos vértices.

Indican cuán extendida está una red.

Un vértice cuya excentricidad alcanza el radio se llama centro del grafo. Esta noción ayuda a elegir ubicaciones relativamente cercanas a todos los puntos de una red.

40.16 Puentes y vértices de articulación

Una arista puente es una arista cuya eliminación aumenta el número de componentes conexas. Un vértice de articulación tiene el mismo efecto al eliminarse junto con sus aristas incidentes.

A—B—C.
La arista B—C es un puente.
El vértice B es de articulación: al quitarlo, A y C quedan separados.

Un ciclo ofrece rutas alternativas y no tiene puentes en sus aristas.

Estas estructuras señalan puntos vulnerables de una red: una falla en un puente o articulación puede aislar una región completa.

40.17 Ciclos eulerianos

Un camino euleriano recorre cada arista exactamente una vez. Un ciclo euleriano además termina en el vértice donde comenzó.

En un grafo no dirigido conexo sin vértices aislados:
hay ciclo euleriano si todos los grados son pares.
hay camino euleriano abierto si exactamente dos vértices tienen grado impar.

La condición se refiere a aristas, no a vértices. Las rutas de reparto, la inspección de conexiones y algunos problemas de trazado se relacionan con recorridos eulerianos.

40.18 Caminos hamiltonianos

Un camino hamiltoniano visita cada vértice exactamente una vez. Un ciclo hamiltoniano también vuelve al origen después de visitar todos los vértices.

Euler: cada arista una vez.
Hamilton: cada vértice una vez.

Son conceptos distintos aunque ambos hablen de recorridos por un grafo.

No existe una condición simple y general tan directa como la de Euler para reconocer ciclos hamiltonianos. Problemas relacionados con visitar todas las ciudades son difíciles y aparecen en optimización de rutas.

40.19 Árboles y conectividad

Un árbol es una forma mínima de mantener conectados n vértices: usa exactamente n - 1 aristas. Si se elimina cualquier arista, deja de estar conectado; si se agrega una, aparece un ciclo.

Árbol = conectado + sin ciclos.

Conectar más aristas agrega redundancia y puede ofrecer rutas alternativas.
Usar menos de n - 1 aristas no alcanza para conectar n vértices.

Esta tensión entre costo y redundancia aparece al diseñar redes. Un árbol reduce conexiones, mientras que los ciclos mejoran la tolerancia a fallos.

40.20 Aplicaciones

  • Rutas entre puntos, navegación y mapas.
  • Detección de dependencias circulares en software.
  • Análisis de alcance y permisos entre entidades conectadas.
  • Identificación de comunidades o islas de una red.
  • Diseño de redes con tolerancia a fallos.
  • Planificación de tareas mediante DAG y orden topológico.

El mismo grafo puede responder preguntas diferentes según se estudien caminos, costos, ciclos o componentes. Elegir la propiedad correcta evita aplicar un algoritmo de navegación a un problema de dependencias, o viceversa.

40.21 Errores frecuentes

  • Contar vértices en lugar de aristas al medir la longitud de un camino.
  • Recorrer una arista dirigida en sentido contrario sin que exista la arista inversa.
  • Confundir un ciclo euleriano con uno hamiltoniano.
  • Olvidar marcar vértices visitados en un recorrido de un grafo con ciclos.
  • Confundir conectividad débil con conectividad fuerte en digrafos.
  • Aplicar distancia por cantidad de aristas cuando el problema necesita pesos.

40.22 Qué debes recordar y conclusión

  • Un camino conecta vértices mediante aristas consecutivas; su longitud cuenta aristas.
  • Un ciclo vuelve al origen y puede representar redundancia o una dependencia circular.
  • Un grafo no dirigido es conexo si todos los pares de vértices se alcanzan.
  • Las componentes conexas son las regiones máximas de alcance mutuo.
  • En digrafos se distinguen conectividad fuerte y débil.
  • Distancia, puentes, ciclos y árboles ayudan a analizar rutas y robustez de redes.

Camino, ciclo y conectividad convierten una lista de conexiones en propiedades útiles para resolver problemas. En el próximo tema estudiaremos algoritmos sobre grafos que automatizan estas exploraciones y optimizaciones.