26. Camino mínimo

El problema del camino mínimo busca una ruta entre vértices cuyo costo total sea el menor posible. La respuesta depende de cómo se valoran las aristas y de las propiedades de esos pesos.

26.1 Introducción

Saber que un destino es alcanzable no siempre es suficiente. En una red vial queremos minimizar distancia o tiempo; en comunicaciones, latencia; en logística, costo; y en un juego, cantidad de movimientos.

El problema del camino mínimo consiste en encontrar, entre todos los caminos que conectan un origen con un destino, aquel cuya suma de costos sea menor.

26.2 Camino, longitud y costo

Un camino es una secuencia de vértices conectados por aristas. Debemos distinguir dos medidas:

MedidaDefinición
LongitudCantidad de aristas utilizadas
Costo o pesoSuma de los valores asociados a las aristas

En un grafo sin pesos, cada arista puede considerarse de costo 1 y ambas medidas coinciden. En un grafo ponderado, el camino con menos aristas no tiene por qué ser el más barato.

26.3 Costo de un camino

Si P = (v₀, v₁, ..., vₖ) es un camino y w(u, v) representa el peso de una arista, su costo es:

costo(P) = w(v₀,v₁) + w(v₁,v₂) + ... + w(vₖ₋₁,vₖ)

La distancia mínima δ(s, t) es el menor costo entre todos los caminos desde s hasta t. Si t no es alcanzable desde s, se utiliza el valor infinito.

26.4 No siempre significa distancia física

Los pesos modelan el criterio que deseamos optimizar:

  • kilómetros de una carretera;
  • minutos de viaje;
  • precio de un traslado;
  • latencia de una conexión;
  • consumo de energía;
  • cantidad de transbordos o riesgo estimado.

Una misma red puede producir rutas óptimas diferentes según la métrica elegida.

26.5 Variantes del problema

VariantePregunta
Un origen, un destino¿Cuál es la mejor ruta de s hasta t?
Un origen, todos los destinos¿Cuáles son las distancias desde s?
Todos los pares¿Cuál es la distancia entre cada par de vértices?
Varios orígenes¿Cuál fuente llega con menor costo a cada vértice?

26.6 Simulación interactiva: compara rutas

Explora las rutas simples de A hasta F. Cada paso resalta un camino y suma sus pesos. Observa que utilizar menos aristas no garantiza obtener el costo mínimo.

Ruta actual

Suma de pesos

Evaluación

Pulsa Siguiente ruta para comenzar.
Se encontraron rutas simples de A hasta F.
Ruta0 / 8
Aristas utilizadas
Costo actual
Mejor costo visto

Verde marca la ruta evaluada. El botón Menos aristas elige A → D → F, pero su costo es mayor que el de la ruta óptima.

26.7 Subestructura óptima

Los caminos mínimos poseen una propiedad esencial: cualquier subcamino de un camino mínimo también debe ser mínimo entre sus propios extremos.

Si s ⇝ t es mínimo y contiene u ⇝ v, entonces u ⇝ v también es mínimo.

Si existiera un subcamino más barato, podríamos reemplazar el original y obtener una ruta total de menor costo, contradiciendo que era óptima.

26.8 Estimaciones de distancia

Los algoritmos suelen mantener una estimación distancia[v] del mejor costo conocido desde el origen hasta v.

distancia[origen] = 0
distancia[otros] = ∞

El infinito indica que todavía no conocemos ningún camino. A medida que se examinan aristas, las estimaciones pueden disminuir.

26.9 Relajación de una arista

Relajar la arista u → v consiste en comprobar si llegar a v pasando por u mejora la distancia conocida.

Si distancia[u] + peso(u,v) < distancia[v]:
distancia[v] = distancia[u] + peso(u,v)
predecesor[v] = u

La relajación es la operación central de Dijkstra, Bellman-Ford y otros algoritmos. Lo que cambia entre ellos es el orden y la cantidad de veces que relajan las aristas.

26.10 Ejemplo de relajación

Supongamos que conocemos distancia[A] = 4, la arista A → B pesa 3 y la mejor estimación actual para B es 10.

4 + 3 = 7 < 10 ⇒ actualizar distancia[B] a 7

Si la estimación de B fuera 6, pasar por A no produciría una mejora y no se modificaría ningún valor.

26.11 Reconstrucción mediante predecesores

Las distancias indican el costo, pero no describen la ruta. Cada vez que una relajación mejora a v guardamos el vértice u como su predecesor.

destino → predecesor[destino] → ... → origen

La cadena se construye en sentido inverso y después se invierte:

function reconstruirCamino(predecesor, origen, destino) {
  const camino = [];

  for (let actual = destino; actual != null;
       actual = predecesor[actual]) {
    camino.push(actual);
  }

  camino.reverse();
  return camino[0] === origen ? camino : null;
}

26.12 Grafos sin pesos

Cuando todas las aristas valen lo mismo, BFS encuentra el camino mínimo en cantidad de aristas. Los vértices se descubren por niveles de distancia creciente.

Grafo sin pesos o pesos iguales → BFS → O(V + E)

Usar un algoritmo ponderado en este caso puede funcionar, pero agrega complejidad innecesaria.

26.13 Pesos positivos, negativos y ciclos negativos

PesosAlgoritmo habitualObservación
Todos igualesBFSMinimiza cantidad de aristas
No negativosDijkstraPuede fijar distancias de forma voraz
Puede haber negativosBellman-FordTambién detecta ciclos negativos alcanzables
Todos los paresFloyd-WarshallTrabaja con una matriz de distancias

Elegir el algoritmo incorrecto puede producir resultados falsos. Dijkstra, por ejemplo, no es válido en general cuando existen pesos negativos.

26.14 Qué ocurre con un ciclo negativo

Un ciclo negativo tiene una suma de pesos menor que cero. Si es alcanzable desde el origen y permite continuar hacia el destino, podemos recorrerlo repetidamente y reducir el costo sin límite.

costo del ciclo < 0 ⇒ no existe un camino mínimo finito para los destinos afectados

En ese caso no se trata simplemente de encontrar una ruta muy barata: el valor óptimo tiende a −∞.

26.15 Grafos dirigidos y no dirigidos

Los algoritmos de camino mínimo pueden aplicarse a ambos tipos. Una arista no dirigida {u, v} suele representarse como dos aristas dirigidas u → v y v → u con el mismo peso.

Un peso negativo en un grafo no dirigido crea inmediatamente un ciclo negativo: podemos ir por la arista y regresar por ella, acumulando dos veces ese valor negativo.

26.16 Árbol de caminos mínimos

Cuando calculamos las mejores rutas desde un origen hacia todos los vértices, las relaciones de predecesor forman habitualmente un árbol dirigido con raíz en el origen.

Este árbol permite reconstruir una ruta mínima hacia cada destino alcanzable. No debe confundirse con un árbol generador mínimo: uno optimiza rutas desde una raíz y el otro minimiza el peso total usado para conectar toda la red.

EstructuraObjetivo
Árbol de caminos mínimosMinimizar la distancia desde un origen
Árbol generador mínimoMinimizar el peso total de las aristas elegidas

26.17 Errores comunes

  • Confundir el camino con menos aristas con el de menor peso.
  • Sumar vértices en lugar de pesos de aristas.
  • No representar con infinito los destinos todavía desconocidos.
  • Actualizar una distancia sin guardar su predecesor.
  • Aplicar Dijkstra a un grafo con pesos negativos.
  • Confundir camino mínimo con árbol generador mínimo.
  • No distinguir un destino inalcanzable de uno afectado por un ciclo negativo.

26.18 Qué debes recordar de este tema

  • El camino mínimo minimiza la suma de los pesos.
  • En grafos sin pesos, BFS minimiza la cantidad de aristas.
  • La relajación intenta mejorar una distancia pasando por una arista.
  • Los predecesores permiten reconstruir la ruta óptima.
  • La presencia de pesos negativos condiciona el algoritmo.
  • Un ciclo negativo puede impedir que exista un mínimo finito.
  • El algoritmo adecuado depende del tipo de pesos y de las consultas requeridas.

26.19 Conclusión

El problema del camino mínimo combina modelado y algoritmo: primero debemos decidir qué representa el costo y después elegir un método compatible con los pesos. Distancias, relajaciones y predecesores forman el lenguaje común de sus principales soluciones.

En el próximo tema estudiaremos Dijkstra, un algoritmo voraz para caminos mínimos cuando todas las aristas tienen pesos no negativos.