ponte

Un ponte è un arco la cui eliminazione disconnette un grafo (ovvero aumenta il numero di componenti connesse). Equivalentemente, un arco è un ponte se e solo se non è contenuto in nessun ciclo.

  • un grafo può non avere nessun ponte (esempio: un ciclo), o essere composto esclusivamente da ponti (esempio: un albero)

center

determinare l’insieme dei ponti di un grafo

Una prima soluzione si basa sulla ricerca esaustiva: si prova, per ogni arco del grafo, se questo è un ponte o no.

Verificare se un arco è un ponte per richiede : basta eliminare l’arco da ed effettuare una DFS per controllare se rimane raggiungibile da .

  • la complessità sarebbe

Il problema è in realtà risolvibile in , usando un'unica visita DFS

L’intuizione si basa sul fatto che i ponti vanno ricercati unicamente tra i archi dell’albero DFS:

  • un arco non presente nell’albero DFS non può essere ponte perché, anche se venisse eliminato, gli archi dell’albero DFS garantirebbero la connessione.

Notiamo che gli archi che non sono ponti sono coperti da archi non attraversati durante la visita.

proprietà

Sia un arco dell’albero DFS con padre di . L’arco è un ponte se e solo se non ci sono archi tra i nodi del sottoalbero radicato in e il nodo o nodi antenati di

La logica da seguire è quindi questa:

Per ogni arco padre-figlio presente nell’albero DFS, il nodo è in grado di scoprire se l’arco è un ponte in questo modo: per ogni nodo :

  • calcola la sua altezza nell’albero
  • calcola e restituisce al padre l’altezza minima che si può raggiungere con archi che partono da nodi del suo sottoalbero diversi da

Il nodo confronta la sua altezza con quella ricevuta: perché sia ponte, l’altezza di deve essere minore di quella restituita dal figlio.

quindi

  • nodo esplora il proprio sottoalbero e restituisce : il minimo livello da sé raggiungibile (utilizzando anche archi all’indietro)
  • nodo confronta con la propria altezza - se , l’arco è un ponte (è l’unico collegamento); altrimenti, un c’è un percorso alternativo e l’arco non è un ponte

center

def DFSp(G, x, padre, altezza, ponti):
	if padre == -1:
		altezza[x] = 0 # primo nodo
	else:
		altezza[x] = altezza[padre] + 1
	
	min_raggiungibile = altezza[x]
	
	for y in G[x]:
		if altezza[y] == -1: # non visitato
			b = DFSp(y, x, altezza, ponti)
			
			if b > altezza[x]:
				ponti.append((x,y))
			
			min_raggiungibile = min(min_raggiungibile, b)
		
		elif y != padre: # già visitato ma non padre: arco all'indietro
			min_raggiungibile = min(min_raggiungibile, altezza[y])
			
			# visto che (x,y) è un arco all'indietro, il min raggiungibile sarà sicuramente <= altezza[y] (y potrebbe arrivare ancora più indietro)
	
	return min_raggiungibile
 
def ponti(G):
	altezza = [-1]*len(G)
	ponti = []
 
	DFSp(G, 0, -1, altezza, ponti) 
	# i ponti si troveranno dentro "ponti"