Memodifikasi algoritma Dijkstra untuk bobot tepi yang diambil dari rentang

10

Misalkan saya memiliki grafik berarah dengan bobot tepi yang diambil dari rentang mana K adalah konstan. Jika saya mencoba menemukan jalur terpendek menggunakan algoritma Dijkstra , bagaimana saya bisa memodifikasi algoritma / struktur data dan meningkatkan kompleksitas waktu menjadi O ( | V | + | E | ) ?[1,,K]KO(|V|+|E|)

pengguna1675999
sumber
Anda harus lebih spesifik, Apa struktur data Anda? Dan Anda tidak bisa mendapatkan lebih sedikit . Tinjau kuliah. O(V+E)
Jonaprieto
Hanya karena kemungkinan untuk bobot tepi yang berbeda kecil, tidak berarti bahwa jumlah jaraknya kecil.
Joe
3
Pertama simpul warna dari grafik Anda dengan biru, kemudian bagi setiap tepi ukuran menjadi t tepi (dengan menambahkan t - 1 simpul tidak berwarna), kemudian jalankan BFS pada grafik baru ini, untuk menemukan jalur terpendek dari mulai node ke node biru, itu O ( | V | + | E | ) jika Anda memiliki konstanta k . ttt1O(|V|+|E|)k
@ SaeedAmiri mengapa tidak menuliskan ini sebagai jawaban?
Joe
@ Jo karena tidak memodifikasi dijkstra (setidaknya secara langsung tidak terkait dengan dijkstra).

Jawaban:

16

Jika bobot tepi bilangan bulat dalam , Anda dapat mengimplementasikan Dijkstra untuk dijalankan dalam waktu O ( K | V | + | E | ) , mengikuti saran @rrenaud. Berikut ini penjelasan yang lebih eksplisit.{0,1,,K}O(K|V|+|E|)

Kapan saja, kunci (hingga) dalam antrian prioritas berada dalam beberapa rentang , di mana D adalah nilai kunci terakhir yang dihapus dari antrian prioritas. (Setiap kunci setidaknya D , karena urutan kunci dihapus oleh algoritma Dijkstra adalah non-menurun, dan setiap kunci yang paling banyak D + K , karena setiap tombol memiliki nilai d [ u ] + w t ( u , w ) untuk beberapa tepi ( u ,{D,D+1,,D+K}DDD+Kd[u]+wt(u,w) mana d [ u ] adalah jarak dari sumber ke beberapa simpul u yang telah dihapus, jadi d [ u ] D. )(u,w)d[u]ud[u]D

Karena itu, Anda dapat menerapkan antrian prioritas dengan array melingkar dengan ukuran K + 1 , dengan setiap sel berisi ember. Simpan setiap simpul dengan kunci k dalam ember di sel A [ h ( k ) ] di mana . Melacak . Lakukan operasi sebagai berikut:A[0..K]K+1kA[h(k)]h(k)=kmod(K+1)D

  • menghapus-min : Sementara kosong, kenaikan . Kemudian hapus dan kembalikan simpul dari .A[h(D)]DA[h(D)]

  • masukkan dengan kunci : Tambahkan simpul ke ember .kA[h(k)]

  • tombol-turun ke : Memindahkan titik dari ke .kkA[h(k)]A[h(k)]

Memasukkan dan mengurangi kunci adalah operasi waktu konstan, sehingga total waktu yang dihabiskan dalam operasi tersebut adalah . Total waktu yang dihabiskan di delete-min akan ditambah nilai akhir dari . Nilai akhir dari adalah maksimum (terbatas) jarak dari sumber ke setiap simpul (karena menghapus-min yang mengambil iterasi meningkat oleh ). Jarak maksimum paling banyak karena setiap jalur memiliki paling banyak tepi. Dengan demikian, total waktu yang dihabiskan oleh algoritma adalah .O(|V|+|E|)O(|V|)DDiDiK(|V|1)|V|1O(K|V|+|E|)

Neal Young
sumber
Saya suka antrian melingkar, itu jauh lebih baik daripada ide saya pada dasarnya memiliki array ukuran K * v di mana hanya sepotong ukuran av digunakan pada waktu tertentu.
rrenaud
Saya menerapkannya menggunakan daftar yang ditautkan ganda, apakah itu masih berarti O (1) untuk menemukan kunci min?
user1675999
@ user1675999, saya tidak yakin. jika daftar Anda diurutkan berdasarkan kunci, bagaimana Anda memasukkan dan mengurangi kunci secara efisien? jika daftar Anda tidak diurutkan berdasarkan kunci, bagaimana Anda menghapus-min secara efisien?
Neal Young
5

Saya berasumsi di sini bahwa adalah bilangan bulat dan bobot ujung adalah integral. Kalau tidak benar-benar tidak membeli apa-apa, Anda selalu dapat menskala ulang bobot sehingga min edge memiliki biaya dan max memiliki biaya , sehingga masalahnya identik dengan masalah jalur terpendek standar.K1K

Algoritma / sketsa bukti: Menerapkan antrian prioritas dengan cara gila seperti ini sebagai arraydaftar dikunci oleh biaya dan sebaliknya menggunakan algoritma Dijkstra standar. Simpan penghitung yang melacak biaya item minimum di heap. Selesaikan panggilan dequeue setelah item dihapus dengan pemindaian linier . Ya, ini kedengarannya gila, tetapi konstanta memungkinkan Anda menipu dan menipu intuisi algoritme Anda terhadap pemindaian linier. Anda hanya perlu memindai dari penanda min terakhir karena algoritma Disjkstra bagus untuk implementasi antrian Anda. Pada saat ia meminta dequeue, item yang dimasukkan ke dalam antrian selalu lebih besar atau sama dengan minimum sebelumnya. Jalur terpendek yang terpanjang yang mungkin memiliki panjangK×|V|KK×|V|, jadi biaya pemindaian yang diamortisasi adalah jika K adalah konstan.K×|V|=O(|V|)

Radenud
sumber
-2

Anda dapat menggunakan jenis topologi untuk menemukan solusinya, biarkan sumber memiliki derajat 0 lalu, pergi dari setiap tepi dari sumber, jika simpul lain memiliki 0 derajat kemudian masukkan ke dalam antrian dan terus lakukan itu. dalam hal ini (tanpa siklus di dalam grafik) dapat mencapai V + E karena akan melalui setiap titik dan ujung sekali dan hanya sekali.

TIANYANG ZHANG
sumber
Sepertinya tidak ada hubungannya dengan pertanyaan? Pertanyaannya tidak menganggap grafik asiklik, dan solusi Anda tidak menggunakan fakta bahwa bobot diambil dari rentang konstan.
xskxzr