Algoritmi · Grafi orientati

Reti di flusso e flusso massimo

Una rete di tubi, una distribuzione di merci, un insieme di assegnamenti: il problema è far arrivare il più possibile dalla sorgente al pozzo, rispettando i limiti di ogni collegamento.

Prerequisiti: grafi orientati e visite BFS / DFS.

1. Rete e flusso

Una rete di flusso (flow network) è un grafo orientato finito G=(V,E) con due vertici distinti: una sorgente s e un pozzo t (sink). Ogni arco ha una capacità finita e non negativa c(u,v). Il flusso f(u,v) è la quantità che effettivamente percorre quell’arco.

Vincolo di capacità

0f(u,v)c(u,v)

Su ogni arco: niente flusso negativo e niente sovraccarico.

Conservazione

uf(u,v)=wf(v,w)

Per ogni v diverso da s e t, quanto entra deve uscire: i vertici intermedi non accumulano flusso.

Poniamo f(u,v) = 0 quando l’arco non esiste. Usiamo la convenzione del flusso non negativo su ciascun arco originale; non imponiamo f(u,v) = −f(v,u). Il valore del flusso è l’uscita netta dalla sorgente, uguale all’entrata netta nel pozzo:

|f|=vf(s,v)vf(v,s)=vf(v,t)vf(t,v)

Il problema del flusso massimo cerca un flusso ammissibile che massimizzi |f|. Non si sommano i flussi di tutti gli archi: la stessa quantità può attraversarne diversi. Se non esce flusso da t e non ne entra in s, bastano le somme in entrata a t o in uscita da s.

2. La rete residua: aggiungere e ripensare

Per ogni arco originale u → v creiamo due possibilità nella rete residua Gf. Manteniamo soltanto quelle con capacità residua strettamente positiva.

  • Avanti, u → v: capacità c(u,v) − f(u,v). Possiamo aggiungere questa quantità.
  • Indietro, v → u: capacità f(u,v). Possiamo annullare questa quantità già assegnata.

Esempio: un arco di capacità 7 che trasporta 4 lascia 3 unità in avanti e 4 indietro. Un arco inverso non è un nuovo tubo: usarlo riduce il flusso sull’arco originale, liberando risorse per un percorso diverso.

Un cammino aumentante è un cammino da s a t nella rete residua. Il suo collo di bottiglia Δ è la minima capacità residua lungo il cammino. Aumentiamo di Δ sugli archi percorsi in avanti e diminuiamo di Δ su quelli percorsi all’indietro. Il valore totale cresce di Δ.

Δ=minePcf(e)
E se esistono archi originali in entrambe le direzioni?

Conserva una coppia residua distinta per ogni arco, con un riferimento al suo inverso. In alternativa, la capacità residua aggregata da u a v è c(u,v) − f(u,v) + f(v,u): comprende sia lo spazio libero in avanti sia il flusso annullabile in senso opposto. Non sovrascrivere un arco originale con un arco residuo inverso.

3. Una rete, due modi di aumentare il flusso

Le etichette indicano flusso / capacità. Ford–Fulkerson con DFS visita prima a e poi b: così vediamo una scelta che sarà corretta con l’arco inverso b → a. Edmonds–Karp usa BFS e sceglie cammini con il minor numero di archi residui.

Rete di flusso con quattro vertici Sorgente s, pozzo t, vertici intermedi a e b. Capacità: s → a 3, s → b 2, a → b 2, a → t 2, b → t 3. I valori correnti sono riportati anche nella tabella. 0 / 3 0 / 2 0 / 2 0 / 2 0 / 3 s a b t
Blu: archi dell’ultimo aumento. Freccia tratteggiata: cancellazione di flusso. A fine esecuzione, il vertice nel lato S del taglio è evidenziato.
|f| = 0

Flusso iniziale nullo.

Stato degli archi e capacità residue
Arcof / cResidua avantiResidua indietro
s → a0 / 330
s → b0 / 220
a → b0 / 220
a → t0 / 220
b → t0 / 330
Soluzione svolta, anche senza il simulatore
  1. s → a → b → t: Δ = 2, |f| = 2.
  2. s → a → t: Δ = 1, |f| = 3.
  3. s → b → a → t: Δ = 1, |f| = 4. Il passaggio b → a riduce f(a,b) da 2 a 1.
  4. s → b → t: Δ = 1, |f| = 5.

Il flusso finale è (3, 2, 1, 2, 3) nell’ordine della tabella. È massimo: il taglio S = {s}, T = {a,b,t} ha capacità 3 + 2 = 5. Con BFS gli aumenti sono invece s → a → t (2), s → b → t (2), s → a → b → t (1): stesso valore finale, tre aumenti.

4. Il taglio certifica il massimo

Un taglio s–t è una partizione (S,T) di V, con s ∈ S e t ∈ T. La sua capacità c(S,T) è la somma delle capacità degli archi originali da S verso T; quelli da T verso S non si contano.

Per conservazione, il flusso netto attraverso qualsiasi taglio è |f|. Il flusso in avanti non supera la capacità del taglio e quello di ritorno è non negativo: quindi |f| ≤ c(S,T). Il teorema max-flow/min-cut afferma che questo limite si può raggiungere:

maxf|f|=min(S,T)c(S,T)

Perché l’assenza di cammini aumentanti basta

  1. Sia S l’insieme dei vertici raggiungibili da s nella rete residua. Se t non è raggiungibile, (S,V ∖ S) è un taglio.
  2. Ogni arco originale da S a T è saturo: altrimenti il suo arco residuo consentirebbe di raggiungere un altro vertice.
  3. Ogni arco originale da T a S ha flusso zero: altrimenti l’arco residuo inverso attraverserebbe il taglio da S a T.
  4. Quindi |f| = c(S,T). Abbiamo insieme un flusso massimo e un taglio minimo.

In modo equivalente: un flusso è massimo se e solo se non esiste un cammino aumentante nella sua rete residua. Flusso massimo e taglio minimo possono non essere unici.

5. Ford–Fulkerson ed Edmonds–Karp

Ford–Fulkerson è un metodo: ripete gli aumenti finché esiste un cammino residuo. Edmonds–Karp specifica come sceglierlo: una BFS trova quello più corto in numero di archi, non quello con maggiore capacità.

inizializza f = 0 su tutti gli archi
finché esiste un cammino P da s a t nella rete residua:
    Δ = minima capacità residua su P
    per ogni arco residuo e di P:
        residua[e] -= Δ
        residua[inverso(e)] += Δ
    valore += Δ
restituisci f e i vertici raggiungibili da s nel residuo

Nel codice con coppie residue, il flusso di un arco originale si ricava come capacità iniziale meno capacità residua avanti. Ogni aggiornamento deve modificare anche l’inverso.

n = |V|, m = |E|, F = valore del flusso massimo
MetodoTempoCondizioni e significato
Ford–FulkersonO(n + m(1 + F))Capacità intere, flusso iniziale zero, ricerca lineare dei cammini. Ogni aumento vale almeno 1; il limite usuale O(mF) omette l’inizializzazione e presuppone F ≥ 1. È pseudopolinomiale.
Edmonds–KarpO(nm²)O(nm) aumenti, ciascuno con una BFS. Limite polinomiale indipendente dai valori delle capacità; si considera aritmetica esatta e costo unitario delle operazioni.

Entrambi richiedono spazio O(n + m) con liste di adiacenza. Nel limite usuale di Edmonds–Karp si considerano i vertici della rete rilevante; l’inizializzazione di eventuali vertici isolati aggiunge O(n). Le distanze BFS nel residuo non diminuiscono: un arco può diventare il collo di bottiglia solo O(n) volte, da cui O(nm) aumenti.

Con capacità razionali Ford–Fulkerson termina, ma scalare a interi può produrre numeri molto grandi. Con capacità irrazionali e scelte arbitrarie dei cammini può non terminare. Con capacità intere esiste un flusso massimo intero, perché ogni aumento conserva l’integralità; non significa che ogni soluzione ottima debba essere intera.

6. Applicazioni

  • Matching bipartito: aggiungi s → L, gli archi L → R e R → t, tutti con capacità 1. Un flusso massimo intero seleziona il massimo numero di coppie disgiunte.
  • Cammini disgiunti per archi: con capacità unitarie, il valore massimo conta quanti cammini s–t possono evitare di condividere archi.
  • Limiti sui vertici: separa v in vin e vout, collegati da un arco con la capacità del vertice; reindirizza gli archi in entrata e in uscita.
  • Più sorgenti o pozzi: aggiungi una supersorgente o un superpozzo, con archi dimensionati sulle disponibilità e sulle richieste. Quando serve una capacità “infinita”, usa un limite finito sufficiente, per esempio la somma delle capacità originali.

Il flusso massimo ottimizza la quantità. Per ottimizzare anche un costo per unità trasportata serve un problema diverso: il flusso a costo minimo.

7. Errori comuni

  • Cercare cammini solo negli archi originali non saturi. Si perdono gli archi inversi e si può arrestare il metodo prima dell’ottimo.
  • Confondere saturo con definitivo. Un arco pieno può essere svuotato parzialmente da un successivo aumento inverso.
  • Sommare entrambe le direzioni di un taglio. La capacità conta solo S → T; il flusso netto sottrae T → S.
  • Interpretare il risultato come un singolo percorso. Il flusso può dividersi su più cammini e una soluzione ammissibile può contenere cicli.

8. Prova prima di aprire la soluzione

1. Un arco ha capacità 9 e flusso 6. Quali sono le capacità residue? E dopo un aumento inverso di 2?

Prima: 3 avanti e 6 indietro. Dopo: il flusso scende a 4, quindi 5 avanti e 4 indietro. L’aumento inverso va inteso come parte di un intero cammino aumentante, per preservare la conservazione.

2. Nell’esempio aumenta soltanto c(a,b) da 2 a 10. Il flusso massimo cresce?

No. Il flusso di valore 5 resta ammissibile e il taglio {s} ha ancora capacità 5. Migliorare un arco non garantisce di migliorare la capacità complessiva.

3. Nel grafo s → a (4), a → t (3), s → t (2), trova un flusso massimo e un taglio minimo.

Invia 3 lungo s → a → t e 2 lungo s → t: valore 5. Il taglio S = {s,a}, T = {t} ha capacità 3 + 2 = 5 e certifica l’ottimalità. L’arco s → a non è saturo.

4. Se t non è raggiungibile da s già nella rete originale, qual è il massimo?

Zero. Il flusso nullo è ammissibile; i vertici raggiungibili da s formano un lato di un taglio senza archi uscenti, quindi di capacità zero.

Per approfondire: Princeton · Maximum Flow per Edmonds–Karp e la sua implementazione; MIT · Network Flows per convenzioni, tagli e dimostrazioni.