Esercizio - Numero di tagli minimi di un grafo, dimostrazione e casi estremi
Testo (domanda da orale).
- Dimostrare che un multigrafo con vertici ha al più tagli minimi.
- Dire quale grafo raggiunge il limite e contare i tagli minimi di: il ciclo ; il cammino con vertici; la stella con centro e foglie; il grafo completo ; il grafo bipartito completo ; i due triangoli collegati da un ponte ( vertici).
- Verificare i conteggi enumerando tutte le bipartizioni.
Soluzione
Punto 1. Sia il taglio minimo e siano i tagli minimi distinti. Per il teorema di Karger, l'algoritmo restituisce proprio con probabilità . Gli eventi «l'output è » sono a due a due disgiunti (l'output è un solo taglio). Quindi Il risultato dice che, anche se i tagli possibili sono , quelli minimi sono pochi.
Punto 2. Il limite è raggiunto dal ciclo, che ha tagli minimi (le coppie di archi), tutti di dimensione ; gli altri grafi dell'elenco ne hanno molti meno.
- : tagli minimi, di dimensione (uno per ogni coppia di archi).
- Cammino con vertici: ha archi, ognuno è un ponte e un taglio di dimensione : tagli minimi ().
- Stella con foglie: tagli minimi (uno per foglia, dimensione ).
- : il grado è , il taglio minimo è e sono minimi i tagli a vertice singolo: tagli (). Un taglio ha archi.
- : grado , taglio minimo , tagli a vertice singolo: tagli ().
- Due triangoli con ponte: il ponte è l'unico taglio di dimensione : .
In generale un albero con vertici ha tagli minimi (uno per arco, ciascuno un ponte).
Punto 3. Enumerando le bipartizioni (con l'ultimo vertice sempre nel lato 0) e contando gli archi tagliati, un programma trova: : dimensione e tagli; cammino: e ; stella: e ; : e ; : e ; due triangoli: e . Per : e .
Risultati: limite dimostrato con eventi disgiunti; nell'ordine dell'elenco; il ciclo raggiunge il limite.
from itertools import combinations
def tagli_minimi(n, E):
miglior, conteggio = None, 0
for m in range(1, 2**(n - 1)): # il vertice n-1 resta sempre nel lato 0
d = sum(((m >> u) & 1) != ((m >> v) & 1) for u, v in E)
if miglior is None or d < miglior: miglior, conteggio = d, 1
elif d == miglior: conteggio += 1
return miglior, conteggio
ciclo = [(i, (i + 1) % 6) for i in range(6)]
print(tagli_minimi(6, ciclo)) # (2, 15)
print(tagli_minimi(6, [(i, i + 1) for i in range(5)])) # (1, 5)
print(tagli_minimi(6, [(0, i) for i in range(1, 6)])) # (1, 5)
print(tagli_minimi(5, list(combinations(range(5), 2)))) # (4, 5)
print(tagli_minimi(6, [(a, b) for a in range(3) for b in range(3, 6)])) # (3, 6)
print(tagli_minimi(6, [(0, 1), (0, 2), (1, 2), (3, 4), (3, 5), (4, 5), (2, 3)])) # (1, 1)Versione ripasso
- Teorema: al più tagli minimi. Prova: Karger restituisce con probabilità ; gli eventi «output » sono disgiunti, la somma è , quindi (Taglio minimo randomizzato - algoritmo di KargerTaglio minimo globale di un multigrafo con n vertici. Algoritmo di Karger: finché restano più di 2 vertici, scegliere un arco uniformemente tra i rimasti e contrarlo (fondere gli estremi, tenere i paralleli, togliere i cappi); gli archi tra i due supervertici finali sono un taglio. Un taglio minimo C di k archi sopravvive se nessun suo arco viene contratto; con n_i vertici il grado minimo è ≥ k, quindi |E_i| ≥ n_i k/2 e Pr[contrarre un arco di C] ≤ 2/n_i; il prodotto telescopico dà Pr[output = C] ≥ 2/(n(n-1)) = 1/C(n,2). Con t = C(n,2) ln(1/δ) ripetizioni indipendenti il fallimento è ≤ δ. Corollario: un grafo ha al più C(n,2) tagli minimi (stretto per il ciclo). Karger-Stein: contrarre fino a n/√2+1 vertici (sopravvive con prob ≥ 1/2) e ricorrere due volte, T(n) = O(n² log n), successo Ω(1/log n).Taglio minimo randomizzato - algoritmo di Karger →).
- Conteggi: : (limite raggiunto, dimensione ); cammino su vertici: (ponti); stella con foglie: ; : (dimensione ); : (dimensione ); due triangoli con ponte: . Albero con vertici: .
- Verifica: enumerazione di tutte le bipartizioni.
- Errori tipici: contare i tagli come insiemi di archi non distinti (due lati scambiati sono lo stesso taglio); credere che un grafo possa avere più di tagli minimi.