Sửa đổi thuật toán của Dijkstra cho các trọng số cạnh được vẽ từ phạm vi


10

Giả sử tôi có một đồ thị có hướng với các trọng số cạnh được vẽ từ phạm vi trong đó không đổi. Nếu tôi đang cố gắng tìm đường đi ngắn nhất bằng thuật toán của Dijkstra , làm cách nào tôi có thể sửa đổi cấu trúc thuật toán / dữ liệu và cải thiện độ phức tạp thời gian thành ?K[1,,K]KO(|V|+|E|)


Bạn nên cụ thể hơn, cấu trúc dữ liệu của bạn là gì? Và bạn không thể nhận được ít . Xem lại bài giảng. O(V+E)
jonaprieto

Chỉ vì khả năng cho trọng lượng cạnh khác biệt nhỏ không có nghĩa là số lượng khoảng cách là nhỏ.
Joe

3
Các đỉnh màu đầu tiên của biểu đồ của bạn có màu xanh lam, sau đó chia từng cạnh có kích thước thành các cạnh (bằng cách thêm các đỉnh không màu ), sau đó chạy BFS trên biểu đồ mới này, để tìm các đường đi ngắn nhất từ ​​nút bắt đầu đến các nút màu xanh nếu bạn có hằng số . t t - 1 O ( | V | + | E | ) kttt1O(|V|+|E|)k

@SaeedAmiri tại sao không viết điều này như một câu trả lời?
Joe

@Joe vì nó không sửa đổi dijkstra (ít nhất là trực tiếp không liên quan đến dijkstra).

Câu trả lời:


16

Nếu trọng số cạnh là số nguyên trong , bạn có thể triển khai Dijkstra để chạy trong thời gian , theo đề xuất của @ rrenaud. Đây là một lời giải thích rõ ràng hơn.O ( K | V | + | E | ){0,1,,K}O(K|V|+|E|)

Bất cứ lúc nào, các khóa (hữu hạn) trong hàng ưu tiên đều nằm trong một số phạm vi , trong đó là giá trị của khóa cuối cùng được xóa khỏi hàng ưu tiên. (Mọi khóa đều ít nhất là , bởi vì chuỗi các khóa được loại bỏ bởi thuật toán của Dijkstra là không giảm và mọi khóa đều có nhiều nhất là , bởi vì mọi khóa đều có giá trị đối với một số cạnh trong đó là khoảng cách từ nguồn đến một số đỉnh đã bị xóa, vì vậy )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

Do đó, bạn có thể triển khai hàng đợi ưu tiên với một mảng tròn có kích thước , với mỗi ô chứa một thùng. Lưu trữ mỗi đỉnh với khóa trong thùng trong ô trong đó . Theo dõi các . Thực hiện các thao tác như sau:K + 1 k A [ h ( k ) ] h ( k ) = k mod ( K + 1 ) DA[0..K]K+1kA[h(k)]h(k)=kmod(K+1)D

  • xóa-min : Trong khi là trống rỗng, increment . Sau đó xóa và trả về một đỉnh từ .D A [ h ( D ) ]A[h(D)]DA[h(D)]

  • chèn bằng khóa : Thêm đỉnh vào nhóm của .A [ h ( k ) ]kA[h(k)]

  • phím giảm đến : Di chuyển đỉnh từ sang .k A [ h ( k ) ] A [ h ( k ) ]kkA[h(k)]A[h(k)]

Phím chèn và phím giảm là các thao tác thời gian không đổi, vì vậy tổng thời gian dành cho các thao tác đó sẽ là . Tổng thời gian dành cho delete-min sẽ cộng với giá trị cuối cùng của . Giá trị cuối cùng của là khoảng cách tối đa (hữu hạn) từ nguồn tới bất kỳ đỉnh nào (vì một lần xóa có lần lặp tăng lên ). Khoảng cách tối đa nhiều nhất là vì mỗi đường dẫn có nhiều nhất cạnh. Do đó, tổng thời gian dành cho thuật toán là .O ( | V | ) D D i D i K ( | V | - 1 ) | V | - 1 O ( K | V | + | E | )O(|V|+|E|)O(|V|)DDiDiK(|V|1)|V|1O(K|V|+|E|)


Tôi thích hàng đợi hình tròn, điều đó tốt hơn ý tưởng của tôi về cơ bản là có một mảng kích thước K * v trong đó chỉ có lát cắt cỡ av được sử dụng tại bất kỳ thời điểm nào.
rrenaud

Tôi đã triển khai nó bằng cách sử dụng danh sách liên kết kép, điều đó vẫn có nghĩa là O (1) để tìm khóa min?
dùng1675999

@ user1675999, tôi không chắc. nếu danh sách của bạn được sắp xếp theo khóa, làm thế nào để bạn chèn và giảm phím một cách hiệu quả? nếu danh sách của bạn không được sắp xếp theo khóa, làm thế nào để bạn xóa hiệu quả?
Neal Young

5

Tôi giả sử ở đây rằng là một số nguyên và trọng số cạnh là không thể thiếu. Mặt khác, nó không thực sự mua cho bạn bất cứ thứ gì, bạn luôn có thể bán lại trọng số sao cho cạnh tối thiểu có giá và tối đa có giá , do đó, vấn đề này giống hệt với vấn đề đường đi ngắn nhất tiêu chuẩn.1 KK1K

Thuật toán / bằng chứng phác thảo: Thực hiện hàng đợi ưu tiên theo cách điên rồ này như một mảng củaliệt kê khóa bằng chi phí và sử dụng thuật toán Dijkstra tiêu chuẩn. Giữ một bộ đếm theo dõi chi phí của mặt hàng tối thiểu trong heap. Giải quyết cuộc gọi dequeue sau khi các mục bị xóa bằng cách quét tuyến tính . Vâng, loại âm thanh điên rồ này, nhưng không đổi hãy để bạn gian lận và đánh lừa trực giác thuật toán của bạn chống lại quét tuyến tính. Bạn chỉ cần quét từ điểm đánh dấu tối thiểu cuối cùng vì thuật toán của Disjkstra rất tốt cho việc thực hiện hàng đợi của bạn. Vào thời điểm nó yêu cầu một dequeue, các mục được chèn vào hàng đợi luôn lớn hơn hoặc bằng mức tối thiểu trước đó. Con đường ngắn nhất dài nhất có thể có độ dàiK K × | V | K × | V | = O ( | V | )K×|V|KK×|V|, vì vậy chi phí quét khấu hao của bạn là nếu K không đổi.K×|V|=O(|V|)


-2

bạn có thể sử dụng sắp xếp tôpô để tìm giải pháp, để nguồn có độ 0 sau đó, đi từ mỗi cạnh từ nguồn, nếu một đỉnh khác có 0 độ thì đặt nó vào hàng đợi và tiếp tục làm điều đó. trong trường hợp này (không có chu kỳ bên trong biểu đồ) nó có thể đạt được V + E vì nó sẽ đi qua mọi đỉnh và cạnh một lần và chỉ một lần.


Có vẻ không liên quan đến câu hỏi? Câu hỏi không cho rằng đồ thị là chu kỳ và giải pháp của bạn không sử dụng thực tế là các trọng số được rút ra từ một phạm vi không đổi.
xskxzr
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.