Algoritmo efficiente per il recupero della chiusura transitiva di un grafico aciclico diretto


14

Sto cercando di risolvere un problema grafico (non è per i compiti, solo per esercitarmi nelle mie abilità). Viene indicato un DAG , dove è l'insieme dei vertici ed i bordi. Il grafico è rappresentato come un elenco di adiacenza, quindi è un insieme contenente tutte le connessioni di . Il mio compito è quello di trovare quale i vertici sono raggiungibili da ogni vertice . La soluzione che uso ha una complessità di , con chiusura transitiva, ma ho letto che in un blog può essere più veloce, anche se non ha rivelato come. Qualcuno potrebbe dirmi un altro modo (con maggiore complessità) per risolvere il problema della chiusura transitiva in un DAG?V E A v v v V O ( V 3 )G(V,E)VEAvvvVO(V3)




Tuttavia, il mio suggerimento è di mantenere la . ma prova a ridurre il numero di confronti in media. Cioè, fai delle ipotesi e aggiungi semplici regole al tuo algoritmo. Puoi usare la moltiplicazione di matrici - ma se la usi per piccoli grafici - allora è solo un casino e in pratica il tuo metodo è migliore. O(|V|3)
AJed

@AJed In questo particolare problema, supererà il limite di tempo. O(V3)
Rontogiannis Aristofanis,

2
@RondogiannisAristophanes Quando dici il limite di tempo, vuoi dire che questo è un problema in alcune sfide di programmazione / algoritmo come topcoder ecc? In tal caso e se si è certi di aver implementato correttamente una soluzione , è possibile che si desideri esaminare nuovamente il problema. Potrebbero esserci altre proprietà nascoste che potrebbero semplificare le cose o potrebbe esserci un modo migliore per esprimere il problema in modo che non sia necessaria una chiusura transitiva. Perché la chiusura transitiva è dura quanto la moltiplicazione della matrice. Leggi student.cs.uwaterloo.ca/~cs466/Old_courses/F08/…O(V3)
Paresh

Risposte:


8

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)nmO(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)


1
Probabilmente potresti usare una rappresentazione dell'elenco collegato per i set e finirebbero per condividere le code comuni.
Kyle Butt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.