Modifica dell'algoritmo di Dijkstra per i pesi dei bordi disegnati dall'intervallo


10

Supponiamo di avere un grafico diretto con pesi dei bordi disegnati dall'intervallo dove è costante. Se sto cercando di trovare il percorso più breve usando l'algoritmo di Dijkstra , come posso modificare l'algoritmo / la struttura dei dati e migliorare la complessità temporale su ?[1,,K]KO(|V|+|E|)


Dovresti essere più specifico, Qual è la tua struttura di dati? E non puoi ottenere meno . Ripassa le lezioni. O(V+E)
Jonaprieto,

Solo perché le possibilità di contrappesi distinti sono piccole non significa che il numero di distanze sia ridotto.
Joe,

3
Primi vertici di colore del tuo grafico con il blu, quindi suddividi ogni bordo della dimensione in bordi (aggiungendo vertici non colorati), quindi esegui il BFS su questo nuovo grafico, per trovare i percorsi più brevi dal nodo iniziale ai nodi blu, è se hai costante . ttt1O(|V|+|E|)k

@SaeedAmiri perché non scriverlo come risposta?
Joe,

@Joe perché non sta modificando dijkstra (almeno direttamente non è correlato a dijkstra).

Risposte:


16

Se i pesi dei bordi sono numeri interi in , è possibile implementare Dijkstra's per l'esecuzione nel tempo , seguendo il suggerimento di @ rrenaud. Ecco una spiegazione più esplicita.O ( K | V | + | E | ){0,1,,K}O(K|V|+|E|)

In qualsiasi momento, le chiavi (finite) nella coda di priorità sono in un intervallo , dove è il valore dell'ultima chiave rimossa dalla coda di priorità. (Ogni chiave è almeno , perché la sequenza di chiavi rimossa dall'algoritmo di Dijkstra non è decrescente, e ogni chiave è al massimo , perché ogni chiave ha valore per alcuni bordo dove è la distanza dalla sorgente a un vertice che è già stato rimosso, quindi )D D D + K d [ u ] + w t ( u , w ) ( u , w ) d [ u ] u d [ u ] D{D,D+1,,D+K}DDD+Kd[u]+wt(u,w)(u,w)d[u]ud[u]D

Per questo , è possibile implementare la coda di priorità con un array circolare di dimensioni , con ogni cella contenente un bucket. Memorizza ciascun vertice con la chiave nel bucket nella cella dove . Tenere traccia di . Eseguire le operazioni come segue:K + 1 k A [ h ( k ) ]A[0..K]K+1kA[h(k)]h(k)=kmod(K+1)D

  • delete-min : Mentre è vuoto, incremento . Quindi eliminare e restituire un vertice da .A[h(D)]DA[h(D)]

  • inserisci con chiave : aggiungi il vertice al bucket di .kA[h(k)]

  • tasto di riduzione da a : sposta il vertice da a .kkA[h(k)]A[h(k)]

I tasti Inserisci e Diminuisci sono operazioni a tempo costante, quindi il tempo totale impiegato in tali operazioni sarà . Il tempo totale trascorso in delete-min sarà più il valore finale della . Il valore finale di è il massimo (finito) la distanza dalla sorgente di qualsiasi vertice (perché un delete-min che prende iterazioni aumenti da ). La distanza massima è al massimo perché ogni percorso ha al massimo spigoli. Pertanto, il tempo totale impiegato dall'algoritmo è .O(|V|+|E|)O(|V|)DDiDiK(|V|1)|V|1O(K|V|+|E|)


Mi piace la coda circolare, è molto meglio della mia idea di avere fondamentalmente un array di dimensioni K * v in cui viene utilizzata solo una sezione di dimensioni av in un dato momento.
rrenaud,

L'ho implementato usando un doppio elenco collegato, significa che è ancora O (1) per trovare la chiave min?
user1675999

@ user1675999, non sono sicuro. se l'elenco è ordinato per chiave, come si inserisce e diminuisce la chiave in modo efficiente? se l'elenco non è ordinato per chiave, come si fa a eliminare-min in modo efficiente?
Neal Young,

5

Suppongo che sia un numero intero e che i pesi del bordo siano integrali. Altrimenti non ti compra davvero nulla, puoi sempre ridimensionare i pesi in modo che il bordo minimo abbia un costo e il massimo abbia un costo , quindi il problema è identico al problema del percorso più corto standard.K1K

Algoritmo / bozza di prova: implementa la coda di priorità in questo tipo di modo folle come una matrice dielenchi codificati in base al costo e altrimenti utilizzano l'algoritmo standard Dijkstra. Mantieni un contatore che tiene traccia del costo dell'articolo minimo nell'heap. Risolvi la chiamata di dequeue dopo che gli elementi sono stati eliminati mediante scansione lineare . Sì, questo tipo di suono sembra folle, ma la costante permette di imbrogliare e ingannare la tua intuizione algoritmica contro le scansioni lineari. Devi solo scansionare dall'ultimo marcatore dell'ultimo minuto perché l'algoritmo di Disjkstra è adatto alla tua implementazione della coda. Quando richiede un dequeue, gli elementi inseriti nella coda sono sempre maggiori o uguali al minimo precedente. Il percorso più breve più lungo possibile ha lunghezzaK×|V|KK×|V|, quindi il costo di scansione ammortizzato è se K è costante.K×|V|=O(|V|)


-2

puoi usare l'ordinamento topologico per trovare la soluzione, lasciare che l'origine abbia un grado 0, quindi passare da ciascun bordo dall'origine, se un altro vertice ha 0 gradi, inseriscilo nella coda e continua a farlo. in questo caso (senza ciclo all'interno del grafico) può ottenere V + E come attraverserebbe ogni vertice e spigoli una volta e una sola volta.


Sembra estraneo alla domanda? La domanda non presuppone che il grafico sia aciclico e la soluzione non si avvale del fatto che i pesi sono disegnati da un intervallo costante.
xskxzr,
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.