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


...
01...0
10...1
...............
01...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

#![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!

Soluzione con DFS