Algoritmi II
Un grafo è una coppia dove è un insieme di vertici ed un insieme di nodi; un grafo si dice
- semplice se ogni coppia di nodi è collegata con al massimo un arco, e non ci sono cappi
- diretto se gli archi sono orientati
- connesso se ogni coppia di nodi è collegata da una passeggiata
- fortemente connesso se per ogni coppia di vertici esiste un cammino da a e viceversa
Due nodi si dicono adiacenti () se sono collegati da un arco, e l'arco si dice incidente rispetto ai due nodi
Rappresentazione
Un grafo si può rappresentare tramite matrice di adiacenza o lista di adiacenza
Matrice di adiacenza
Siano i vertici del grafo, possiamo rappresentare il grafo come una matrice tale che
... | ||||
0 | 1 | ... | 0 | |
1 | 0 | ... | 1 | |
... | ... | ... | ... | ... |
0 | 1 | ... | 0 |
Per verificare se il costo è la dimensione della matrice è con
Lista di adiacenza
Siano i vertici del grafo, possiamo indicare per ogni nodo l'insieme dei suoi vicini
... | |
Per verificare se il costo è la dimensione della matrice è , con
Teoremi
Definizione
Una passeggiata in un grafo è definita come una sequenza dove collega a
Definizione
Una passeggiata si dice euleriana se attraversa ogni arco del grafo esattamente una volta
Teorema di Eulero
una passeggiata euleriana il grafo è connesso ed esistono al massimo 2 vertici di grado dispari
Definizione
Un cammino è una passeggiata che non ripete vertici (quindi neanche archi)
Definizione
Un ciclo in un grafo è un sottografo connesso con ogni vertice di grado 2
Osservazione
Se una passeggiata da a un cammino da a
si dimostra con l'algoritmo
DFS (depth first search)
#![allow(unused)] fn main() { dfs(graph, y, visited) } } } fn dfs_iterative(graph: &[Vec<usize>], x: usize) -> Vec<bool> { let mut stack = Vec::from([x]); let mut visited = vec![false; graph.len()]; let mut adjacent = vec![0; graph.len()]; while let Some(&x) = stack.last() { if let Some(&y) = graph[x].get(adjacent[x]) { if !visited[y] { stack.push(y); visited[y] = true; } adjacent[x] += 1; } else { stack.pop(); }
Dimostrazione correttezza: bisogna dimostrare che
se un cammino da a
per assurdo, supponiamo che
... | ||||
... | ... | ... |
Sia un indice
è stato inserito nello stack ma se stack e stack l'algoritmo non è stato eseguito correttamente (contraddizione!)
TODO: complessità
Definizione
L'albero di visita è un sottografo composto dagli archi che usiamo per raggiungere i vertici nuovi non ancora visitati
- è connesso
- è aciclico
Definizione
L'albero di visita di un grafo diretto è detto arborescenza
- diretto
- ogni arco orientato dalla radice alle foglie
Se è un graffo connesso contiene tutti i nodi del grafo
Se non è connesso è il componennte che contiene
Ordine topologico
Consideriamo un progetto diviso in task, con dipendenze fra i vari task (Es. va eseguito dopo e , e dopo ; in questo caso l'ordine sarebbe )
Indicando i vertici con e gli archi con se dipende da , una programmazione dei task corrisponde ad un ordine dei vertici con tutti gli archi da destra verso sinistra
Se il grafo ha un ciclo (diretto), non è possibile dare un ordine topologico
Dimostrazione
Suppponiamo per assurdo che esiste un tale ordine, allora uno dei vertici deve essere per forza l'ultimo nell'ordine; ma essendo ciclico esiste un arco che va da sinistra verso destra da uno dei vertici "centrali" della sequenza all'ultimo vertice, quindi tale ordine non esiste.
Definizione
Un grafo diretto ha un ordine topologico se un ordine deivertici con tutti gli ordini degli archi da destra verso sinistra
Proposizione
Se un grafo diretto ha la proprietà che ogni vertice ha almeno un arco uscente un ciclo
stessa dimostrazione dell'algoritmo del primo giorno: se ogni vertice ha un arco uscente e i vertici sono finiti, alora prima o poi dovrà tornare... (creare un ciclo)
L'implicazione non è vera!
Corollario
Se \notexists un ciclo un nodo senza archi uscenti
Soluzione naive
TODO: algoritmo per trovare l'ordine topologico!