Si veda la definizione di ponte.
Ricerca esaustiva in
Per ogni arco del grafo si esegue una DFS da escludendo l’arco . Se non viene raggiunto, l’arco è un ponte.
Ricerca efficiente in con l’algoritmo di Tarjan
Si basa sulla relazione tra i ponti e l’albero DFS: gli archi appartenenti a cicli non possono essere ponti, quindi un arco è un ponte se fa parte dell’albero DFS e non è coperto da alcun arco non appartenente all’albero.
Per implementare ciò si memorizzano due valori per ogni nodo :
- disc: il tempo di scoperta (prima visita) del nodo,
- low: il tempo di scoperta del più antico antenato di nell’albero DFS che è raggiungibile partendo da e scendendo lungo zero o più archi dell’albero DFS, per poi usare al più un arco all’indietro.
Se un arco dell’albero ha low[v] > disc[u], allora è un ponte, perché usando gli archi dell’albero DFS non esiste un cammino alternativo dal sottoalbero di a un antenato di .
def cerca_ponti(liste):
disc = [-1] * n
low = [-1] * n
ponti = []
time = [0] # il tempo è passato alla funzione ricorsiva come una lista singleton per rendere il valore mutabile e persistente tra le chiamate ricorsive
dfs_ponti(0, liste, disc, low, -1, time, ponti)
return ponti
def dfs_ponti(nodo, liste, disc, low, padre, time, ponti):
# scoperta del nodo
disc[nodo] = low[nodo] = time[0]
time[0] += 1
for vicino in liste[nodo]:
if vicino == padre:
continue
if disc[vicino] != -1: # il vicino è stato scoperto prima del nodo corrente
# arco all'indietro
low[nodo] = min(low[nodo], disc[vicino])
else:
dfs_ponti(vicino, liste, disc, low, nodo, time, ponti):
# controllo del ponte dopo la DFS del figlio
if low[vicino] > disc[nodo]:
ponti.append((nodo, vicino))
low[nodo] = min(low[nodo], low[vicino])