grafi

Un grafo è formato da:

  • nodi
  • archi

Un grafo si indica come: , con:

  • insieme dei vertici,
  • insieme degli archi coppie di nodi

Si ha:

  • (numero di vertici)
  • (numero di archi)

grado di un nodo

Il grado di un nodo è il numero di archi che incidono su un nodo.

somma dei gradi dei vertici, handshaking lemma

Dato un grafo , si ha che

(la somma dei gradi di tutti i nodi è pari a ).

(si vede chiaramente che, per ogni arco , esistono esattamente due nodi ad esso incidenti, e di cui quindi esso aumenta il grado di 1)

corollario (handshaking lemma): Dato un grafo , il numero dei nodi di che hanno grado dispari è pari.

Se ha almeno due nodi, allora in ci sono due nodi con lo stesso grado.

Prendiamo un grafo con . Ogni nodo può avere un grado che va da a (ci sono quindi possibili gradi).

Se tutti gli nodi avessero grado diverso, allora vorrebbe dire necessariamente che un nodo dovrebbe avere grado , e un altro . Ma la coesistenza di un nodo con grado e uno con grado è impossibile (se un nodo è connesso a tutti gli altri, non ce ne può essere un altro completamente isolato). Si ha quindi necessariamente che almeno due nodi hanno lo stesso grado.

nodi adiacenti

Due nodi si dicono adiacenti se l’arco (se sono connessi da un arco).

grafi diretti e indiretti

Un grafo si dice diretto se i suoi archi hanno una direzione. Altrimenti, si dice indiretto.

center

(a sinistra un grafo indiretto, a destra un grafo diretto)

numero di archi

  • Se il grafo è diretto, il numero degli archi è: .
  • Se invece il grafo è non diretto, .

In entrambi i casi quindi, il numero di archi è in (con ).

pozzo

In un grafo diretto, un pozzo è un nodo senza archi uscenti.

  • un pozzo universale è un pozzo verso cui tutti gli altri nodi hanno un arco.

center

(a sinistra un pozzo, a destra un pozzo universale)

grafi sparsi e densi

Un grafo si dice sparso se (“ha pochi archi”). Un grafo si dice invece denso se .

Esempi di grafi densi:

  • un grafo si dice completo se ha tutti gli archi ()
  • un grafo diretto si dice torneo se tra ogni coppia di nodi c’è esattamente un arco

Esempio di grafo sparso:

  • un grafo planare è un grafo che si può disegnare sul piano senza che gli archi si intersechino.

grafo planare

center

più piccolo grafo non planare

center

un grafo non sparso non è necessariamente denso!

esistono anche grafi con archi.

alberi

def

Un albero è un grafo sparso connesso (ogni nodo è connesso agli altri) senza cicli.

Un albero ha sempre archi.

Tutti gi alberi sono grafi planari.

rappresentare i grafi

rappresentazione tramite matrice

Uno dei modi più semplici per rappresentare un grafo è quello della matrice di adiacenza.

Dato un grafo di nodi, si costruisce una matrice binaria con:

  • c’è un arco diretto da a
  • Uno dei problemi principali di questa matrice è lo spreco di spazio: se per esempio il grafo è sparso, si occuperanno solo fino a delle posizioni.
  • Uno dei vantaggi principali è invece la velocità con cui si può controllare la presenza di un arco: basta accedere all’elemento in posizione - costa .

rappresentazione tramite lista di adiacenza

Si utilizza una lista di liste , con tanti elementi quanti sono i nodi del grafo .

  • ogni elemento è una lista che contiene i nodi adiacenti al nodo .
  • Rispetto alla rappresentazione tramite matrice, il risparmio di spazio è notevole.
  • Però, vedere se due archi sono connessi o meno può arrivare a costare (bisogna scorrere la lista dei nodi adiacenti al nodo per verificare se sia presente).

esercizio: verificare se un grafo diretto ha un pozzo universale

In questo caso, è più comodo utilizzare la rappresentazione tramite matrice - essa ci permette infatti di risolvere il problema in .

Osserviamo un esempio di un pozzo universale in questa rappresentazione:

C’è un semplice test che ci permette di eliminare uno dei due nodi rappresentati da ogni posizione della matrice:

  • se , sicuramente so che (la riga, ovvero il nodo da cui l’arco parte) non è un pozzo infatti, c’è un arco che parte da esso
  • se , so che non è pozzo universale non c’è un arco entrante in (ma potremmo trovarci nella situazione dell’esempio, quindi non escludiamo )

Quindi, una soluzione sarebbe:

def pozzo(M):
n = len(M)
L = [x for x in range(n)]; # creo una lista con tutti i nodi
 
# prendo due nodi per controllare
while len(L)>1:
	a = L.pop() # uso pop perché è O(1)
	b = L.pop()
	if M[a][b]: # se è 1
		L.append(b) # a non è pozzo, quindi teniamo b
	else:
		L.append(a) # b non è pozzo universale, quindi teniamo a
 
L.pop()
for j in range(n): # controllo la riga 
	if M[x][j]: 
		return False # se non sono tutti zeri, non è pozzo univ.
 
for i in range(n):
	if i != x and M[i][x] == 0:
		return False # se ci sono zeri oltre a quello in (x,x), ""
 
return True