Il fatto che il nostro grafico sia aciclico rende questo problema molto più semplice.
L'ordinamento topologico può darci un ordinamento dei vertici tale che, se i < j , allora non c'è bordo da v j indietro a v iv1,v2,…,vni<jvjvi . Abbiamo elencato i vertici in modo tale che tutti gli spigoli vadano "avanti" nel nostro elenco.
(modificato per correggere l'analisi e dare un algoritmo leggermente più veloce)
Ora andiamo indietro attraverso questo elenco, iniziando dall'ultimo vertice . La chiusura transitiva di v n è solo se stessa. Anche aggiungere v n alla chiusura transitiva di ogni vertice con un bordo di v n .vnvnvnvn
Per ogni altro vertice , andando dall'estremità all'indietro, prima aggiungi v i alla sua chiusura transitiva, quindi aggiungi tutto nella chiusura transitiva di v i alla chiusura transitiva di tutti i vertici con un bordo a v i .vivivivi
Il tempo di esecuzione è nel peggiore dei casi, con n il numero di vertici e m ∈ O ( n 2 ) il numero di bordi. L'ordinamento topologico richiede tempo O ( n + m ) . Quindi eseguiamo un'altra O ( m n ) nel passaggio all'indietro: mentre procediamo all'indietro nell'elenco, per ogni bordo, dobbiamo aggiungere fino a nO(n+m+nm)=O(n3)nm∈O(n2)O(n+m)O(mn)n vertici alla chiusura transitiva di qualcuno.
Si noti che è possibile ottenere una piacevole accelerazione a fattore costante rappresentando la chiusura transitiva di tutti mediante matrici di bit. Supponiamo che tu abbia avuto solo ; allora si dovrebbe utilizzare un singolo a 64 bit int in cui il bit i è 1 se i è nel mio chiusura transitiva e 0 altrimenti. Poi la parte in cui si aggiunge tutto in i 'chiusura transitiva s a j ' s è veramente veloce: Abbiamo appena prendiamo c j | = c i . (Operazione binaria OR.)n=64iiijcjci
Per , dovresti tenerli negli array e fare un po 'di aritmetica, ma sarebbe molto più veloce di un set di oggetti.n>64
OO(n3)