Modificación del algoritmo de Dijkstra para pesos de borde extraídos del rango

10

Supongamos que tengo un gráfico dirigido con pesos de borde extraídos del rango [1,,K] donde K es constante. Si estoy tratando de encontrar la ruta más corta utilizando el algoritmo de Dijkstra , ¿cómo puedo modificar la estructura del algoritmo / datos y mejorar la complejidad del tiempo a O(|V|+|E|) ?

usuario1675999
fuente
Debe ser más específico, ¿Cuál es su estructura de datos? Y no puede obtener menos O(V+E) . Revisar conferencias.
jonaprieto
El hecho de que las posibilidades de distintos pesos de borde sean pequeñas no significa que el número de distancias sea pequeño.
Joe
3
Primero coloree los vértices de su gráfico con azul, luego subdivida cada borde de tamaño en t bordes (agregando t - 1 vértices sin color), luego ejecute el BFS en este nuevo gráfico, para encontrar las rutas más cortas desde el nodo de inicio hasta los nodos azules, es O ( | V | + | E | ) si tiene k constante . ttt1O(|V|+|E|)k
@SaeedAmiri ¿por qué no escribir esto como respuesta?
Joe
@Joe porque no está modificando dijkstra (al menos directamente no está relacionado con dijkstra).

Respuestas:

16

Si los pesos de borde son enteros en , puede implementar Dijkstra's para que se ejecute en tiempo O ( K | V | + | E | ) , siguiendo la sugerencia de @ rrenaud. Aquí hay una explicación más explícita.{0,1,,K}O(K|V|+|E|)

En cualquier momento, las teclas (finitas) en la cola de prioridad están en algún rango , donde D es el valor de la última clave eliminada de la cola de prioridad. (Cada clave es al menos D , porque la secuencia de claves eliminadas por el algoritmo de Dijkstra no es decreciente, y cada clave es como máximo D + K , porque cada clave tiene un valor d [ u ] + w t ( u , w ) para un poco de borde ( u ,{D,D+1,,D+K}DDD+Kd[u]+wt(u,w) donde d [ u ] es la distancia desde la fuente a algún vértice u que ya se ha eliminado, entonces d [ u ] D. )(u,w)d[u]ud[u]D

Debido a esto, puede implementar la cola de prioridad con una matriz circular de tamaño K + 1 , con cada celda que contiene un depósito. Almacene cada vértice con la clave k en el depósito en la celda A [ h ( k ) ] donde h ( k ) = k mod ( K + 1 ) . Realizar un seguimiento de D . Realice las operaciones de la siguiente manera:A[0..K]K+1kA[h(k)]h(k)=kmod(K+1)D

  • delete-min : Mientras está vacía, el incremento D . Luego borre y devuelva un vértice de A [ h ( D ) ] .A[h(D)]DA[h(D)]

  • inserte con la tecla : Agregue el vértice al cubo de A [ h ( k ) ] .kA[h(k)]

  • tecla de disminución a k ' : mueve el vértice de A [ h ( k ) ] a A [ h ( k ' ) ] .kkA[h(k)]A[h(k)]

Insertar y disminuir clave son operaciones de tiempo constante, por lo que el tiempo total dedicado a esas operaciones será . El tiempo total de permanencia en delete-min será O ( | V | ) más el valor final de D . El valor final de D es la distancia máxima (finita) desde la fuente a cualquier vértice (porque un delete-min que toma i iteraciones aumenta D en i ). La distancia máxima es como máximo K ( | V | - 1O(|V|+|E|)O(|V|)DDiDi porque cada ruta tiene como máximo | V | - 1 aristas. Por lo tanto, el tiempo total empleado por el algoritmo es O ( K | V | + | E | ) .K(|V|1)|V|1O(K|V|+|E|)

Neal Young
fuente
Me gusta la cola circular, eso es mucho mejor que mi idea de tener básicamente una matriz de tamaño K * v donde solo se usa una porción de tamaño av en un momento dado.
rrenaud
Lo implementé usando una lista de doble enlace, ¿eso todavía significa que es O (1) para encontrar la tecla min?
user1675999
@ user1675999, no estoy seguro. si su lista está ordenada por clave, ¿cómo inserta y disminuye la clave de manera eficiente? si su lista no está ordenada por clave, ¿cómo hacer delete-min de manera eficiente?
Neal Young el
5

Asumo aquí que es un número entero y los pesos de borde son integrales. De lo contrario, realmente no le compra nada, siempre puede volver a escalar los pesos para que el borde mínimo haya costado 1 y el máximo haya costado K , por lo que el problema es idéntico al problema estándar de la ruta más corta.K1K

Algoritmo / bosquejo de prueba: Implemente la cola de prioridad en este tipo de locura como una matriz de listas codificadas por costo y de otro modo usar el algoritmo estándar de Dijkstra. Mantenga un contador que rastree el costo del artículo mínimo en el montón. Resuelva la llamada en cola después de que los elementos se eliminen mediante escaneo lineal . Sí, este tipo de sonido parece una locura, pero constante KK×|V|Kle permite engañar y engañar a su intuición algorítmica contra escaneos lineales. Solo necesita escanear desde el último marcador min porque el algoritmo de Disjkstra es bueno para su implementación de cola. En el momento en que solicita una cola, los elementos insertados en la cola son siempre mayores o iguales al mínimo anterior. El camino más largo más corto posible tiene longitud , entonces su costo de escaneo amortizado es K × | V | = O ( | V | ) si K es constante.K×|V|K×|V|=O(|V|)

rrenaud
fuente
-2

puede usar la clasificación topológica para encontrar la solución, dejar que la fuente tenga un grado 0 y luego ir desde cada borde de la fuente, si otro vértice tiene 0 grados, luego ponerlo en la cola y seguir haciendo eso. en este caso (sin ciclo dentro del gráfico) puede alcanzar V + E ya que atravesaría cada vértice y bordes una y solo una vez.

TIANYANG ZHANG
fuente
Parece no relacionado con la pregunta? La pregunta no asume que el gráfico es acíclico, y su solución no hace uso del hecho de que los pesos se extraen de un rango constante.
xskxzr