34. Algoritmo de Ford-Fulkerson

Ford-Fulkerson obtiene un flujo máximo aumentando repetidamente el flujo a través de caminos de la red residual. Cuando ya no existe un camino desde la fuente hasta el sumidero, el flujo es máximo.

34.1 Introducción

En el tema anterior definimos capacidad, conservación y red residual. Ford-Fulkerson transforma esas ideas en un método general para resolver el problema de flujo máximo.

Se comienza con flujo cero. Mientras la red residual contenga un camino desde la fuente s hasta el sumidero t, se envía por él la mayor cantidad posible.

34.2 Esquema del método

  1. Inicializar todas las aristas con flujo cero.
  2. Construir la red residual correspondiente.
  3. Buscar un camino aumentante desde s hasta t.
  4. Calcular la capacidad mínima del camino.
  5. Actualizar el flujo y repetir.
buscar camino → hallar cuello de botella → aumentar flujo → actualizar residuales

34.3 El flujo inicial

El flujo cero respeta automáticamente las capacidades y la conservación. Al principio, la capacidad residual hacia adelante coincide con la capacidad original y las aristas inversas tienen capacidad cero.

f(u,v) = 0 ⇒ cf(u,v) = c(u,v) y cf(v,u) = 0

También es posible comenzar con cualquier flujo factible, aunque la implementación habitual utiliza cero.

34.4 Búsqueda de un camino aumentante

Se recorre únicamente la red residual: una arista puede usarse si su capacidad residual es positiva. Una búsqueda en profundidad o en anchura permite encontrar un camino.

Ford-Fulkerson no fija la estrategia de búsqueda. El camino elegido puede cambiar el número de iteraciones, aunque con capacidades enteras el valor final será máximo.

34.5 Cuello de botella

El aumento Δ es la menor capacidad residual de las aristas del camino. Esa arista se saturará después de la actualización.

Δ = min cf(u,v) a lo largo del camino aumentante

Enviar una cantidad mayor violaría una capacidad; enviar una menor sería válido, pero desperdiciaría una oportunidad de progreso.

34.6 Simulación paso a paso

Avanza un camino aumentante por vez. Las aristas verdes forman el camino actual; sus etiquetas muestran flujo/capacidad. La lista lateral muestra la capacidad residual hacia adelante.

Capacidades residuales

Camino aumentante

Acción actual

Flujo inicial igual a cero.
Existe un camino aumentante.
Iteración0 / 4
Aumento Δ
Flujo total0
EstadoEn proceso

Al finalizar, las capacidades de entrada al sumidero suman 14 y quedan saturadas. Por ello ningún camino residual puede llegar hasta t.

34.7 Actualización hacia adelante

Si el camino utiliza una arista en su dirección original, se suman Δ unidades a su flujo. Su capacidad residual hacia adelante disminuye en Δ y la inversa aumenta en la misma cantidad.

f(u,v) ← f(u,v) + Δ

34.8 Actualización mediante aristas inversas

Si el camino residual recorre v → u para una arista original u → v, se restan Δ unidades del flujo anterior. Esto permite redirigir capacidad hacia una alternativa mejor.

recorrer la residual v → u ⇒ f(u,v) ← f(u,v) − Δ

Las aristas inversas son la razón por la que una elección temprana no tiene que ser definitiva.

34.9 Pseudocódigo

flujo = 0
mientras exista un camino P desde s hasta t en la red residual:
  delta = mínima capacidad residual de P
  para cada arista (u, v) de P:
    aumentar el flujo si se recorre hacia adelante
    disminuir el flujo si se recorre hacia atrás
  flujo = flujo + delta
devolver flujo

34.10 Búsqueda del camino con DFS

function buscarCaminoDFS(residual, s, t) {
  const padre = Array(residual.length).fill(-1);
  const visitado = Array(residual.length).fill(false);

  function dfs(u) {
    if (u === t) return true;
    visitado[u] = true;
    for (let v = 0; v < residual.length; v++) {
      if (!visitado[v] && residual[u][v] > 0) {
        padre[v] = u;
        if (dfs(v)) return true;
      }
    }
    return false;
  }
  return dfs(s) ? padre : null;
}

34.11 Implementación completa

function fordFulkerson(capacidad, s, t) {
  const n = capacidad.length;
  const residual = capacidad.map(fila => [...fila]);
  let flujoMaximo = 0;
  let padre;

  while ((padre = buscarCaminoDFS(residual, s, t)) !== null) {
    let delta = Infinity;
    for (let v = t; v !== s; v = padre[v]) {
      delta = Math.min(delta, residual[padre[v]][v]);
    }

    for (let v = t; v !== s; v = padre[v]) {
      const u = padre[v];
      residual[u][v] -= delta;
      residual[v][u] += delta;
    }
    flujoMaximo += delta;
  }
  return { flujoMaximo, residual };
}

Si se necesita conocer el flujo de cada arista, se conserva una matriz separada o se compara la capacidad original con la residual.

34.12 Por qué el resultado es máximo

Cuando no existe un camino residual de s a t, tomamos S como los vértices todavía alcanzables desde s y T como el resto. Las aristas originales de S a T están saturadas y las de T a S no transportan flujo neto hacia S.

El valor del flujo coincide entonces con la capacidad del corte (S,T). Por el teorema flujo máximo–corte mínimo, ninguna solución puede ser mejor.

34.13 Terminación con capacidades enteras

Si todas las capacidades son enteras, cada cuello de botella también lo es y cada iteración aumenta el flujo al menos en una unidad.

Capacidades enteras ⇒ a lo sumo |f*| aumentos de una unidad o más

Por eso Ford-Fulkerson termina y su complejidad puede expresarse en función del valor máximo |f*|.

34.14 Capacidades irracionales

Con números irracionales y una elección desafortunada de caminos, el método genérico puede realizar infinitos aumentos y no converger al máximo.

En cálculos con punto flotante también pueden aparecer residuos diminutos por errores numéricos. Conviene utilizar enteros escalados cuando el problema lo permita o establecer una tolerancia.

34.15 Ford-Fulkerson y Edmonds-Karp

Edmonds-Karp es una implementación específica de Ford-Fulkerson que siempre busca el camino aumentante con BFS, es decir, con la menor cantidad de aristas.

MétodoBúsquedaComplejidad
Ford-Fulkerson con DFSCualquier caminoO(E · |f*|) para enteros
Edmonds-KarpBFSO(VE²)

Edmonds-Karp ofrece una cota polinómica independiente del valor numérico del flujo máximo.

34.16 Complejidad

Una búsqueda DFS cuesta O(E). Con capacidades enteras, hay como máximo |f*| iteraciones si cada una aumenta al menos una unidad.

Tiempo: O(E · |f*|)
Espacio: O(V + E) con listas de adyacencia

Esta complejidad es pseudopolinómica: depende del valor de las capacidades, no solo del tamaño de su representación binaria.

34.17 Aplicaciones

  • Calcular capacidad máxima de transporte o comunicación.
  • Resolver emparejamientos máximos bipartitos.
  • Encontrar caminos disjuntos en aristas o vértices.
  • Asignar recursos con restricciones de capacidad.
  • Determinar cortes mínimos y puntos débiles de una red.
  • Resolver problemas de circulación mediante transformaciones.

34.18 Errores comunes

  • Buscar caminos en la red original en vez de la residual.
  • No crear o actualizar las aristas residuales inversas.
  • Usar el mayor valor del camino en vez del mínimo como Δ.
  • Modificar capacidades originales y perder la solución.
  • No marcar vértices visitados durante la búsqueda.
  • Asumir una complejidad polinómica para cualquier elección de caminos.
  • Comparar residuos de punto flotante exactamente con cero.

34.19 Qué debes recordar de este tema

  • Ford-Fulkerson comienza con un flujo factible, normalmente cero.
  • Cada iteración busca un camino en la red residual.
  • El cuello de botella determina cuánto puede aumentarse.
  • Las aristas inversas permiten corregir decisiones anteriores.
  • Sin camino aumentante, el flujo es máximo.
  • Con capacidades enteras, el método termina.
  • Edmonds-Karp utiliza BFS y garantiza O(VE²).

34.20 Conclusión

Ford-Fulkerson mejora una solución local mediante caminos aumentantes hasta que la red residual proporciona un certificado global de optimalidad. Su idea de avanzar y, cuando sea necesario, deshacer flujo es una de las técnicas más importantes de la teoría de grafos.

En el próximo tema estudiaremos emparejamientos en grafos y veremos cómo una selección de pares compatibles puede expresarse como un problema de flujo.