Tôi nên sử dụng thuật toán nào để tìm đường đi ngắn nhất trong biểu đồ này?


8

Tôi có một biểu đồ với khoảng một tỷ đỉnh, mỗi đỉnh được kết nối với khoảng 100 đỉnh khác một cách ngẫu nhiên.

Tôi muốn tìm độ dài của con đường ngắn nhất giữa hai điểm. Tôi không quan tâm đến con đường thực tế được sử dụng.

Ghi chú:

  • Đôi khi các cạnh sẽ bị cắt đứt hoặc thêm vào. Điều này xảy ra ít hơn khoảng 500 lần so với tra cứu. Bạn cũng có thể xử lý các thay đổi cạnh nếu bạn cho phép bạn có hiệu suất tốt hơn.
  • Tôi có thể xử lý trước biểu đồ.
  • Nếu phải mất hơn 6 bước, bạn có thể quay lại với vô cùng.
  • Có thể chấp nhận sai 0,01% thời gian, nhưng chỉ khi trả lại một độ dài quá dài.
  • Tất cả các cạnh có chiều dài là 1.
  • Tất cả các cạnh là hai chiều.

Tôi đang tìm kiếm một thuật toán. Psuedocode, mô tả tiếng Anh và mã thực tế đều tuyệt vời.

Tôi có thể sử dụng A *, nhưng điều đó dường như được tối ưu hóa cho tìm đường.
Tôi đã nghĩ về việc sử dụng thuật toán của Dijkstra , nhưng nó có một bước yêu cầu thiết lập thuộc tính tìm đường đi ngắn nhất của mọi đỉnh thành vô cực

(Nếu bạn đang tự hỏi về trường hợp sử dụng, thì đó là Cuộc thi C Underhanded.)


1
Thuật toán của Dijkstra A * với h = 0, viết vào 'đường dẫn', bạn có nghĩa là bạn không có cách nào để ước tính chi phí tối thiểu tốt hơn?
jk.

1
Đặt thuộc tính tìm đường đi ngắn nhất của mọi đỉnh không có nghĩa là bạn phải viết 'vô cùng' một tỷ lần. Bạn chỉ cần một hàm trả về 'vô cực' khi không có giá trị nào được đặt.
kevin cline

Câu trả lời:


6

Thuật toán cơ bản

Duy trì hai bộ nút bạn có thể tiếp cận từ nút bắt đầu và kết thúc. Trong thời trang xen kẽ, đi ba bước từ cả hai bên. Mỗi lần thay thế tập hợp của bạn bằng các nút, bạn có thể tiếp cận qua một bước nữa. Sau mỗi bước bạn kiểm tra hai bộ cho các nút chung.

Tối ưu hóa

Đảm bảo rằng bạn có thể lặp lại các bộ như đã sắp xếp để bạn có thể tìm kiếm các nút chung trong một lần quét: thao tác O (n + m). Danh sách sẽ có tới một triệu nút mỗi.

Để mở rộng một tập hợp với một bước, bạn đã truy vấn tất cả các kết nối của các nút trong bộ ban đầu và hợp nhất chúng thành một tập hợp được sắp xếp mới. Hợp nhất 2 danh sách được sắp xếp lại có thể được thực hiện trong một lần quét. Vì vậy, bạn cũng muốn đảm bảo rằng bạn có thể truy vấn các kết nối của một nút như đã sắp xếp. (Điều này có thể được xử lý trước).

Trong hai bước cuối, mỗi bộ mới là kết quả của việc hợp nhất tối đa 10000 kết quả truy vấn này. Tốt nhất là thực hiện việc hợp nhất này (hợp nhất các khối có kích thước bằng nhau). Theo cách đó, cấu trúc dữ liệu tập hợp được sắp xếp có thể là một danh sách liên kết đơn giản.

Bằng cách đó, toàn bộ thuật toán trở thành O (6 * n + 6 * n * log n) trong đó n là max. 1.000.000.


Làm thế nào để bạn kiểm tra tư cách thành viên trong một danh sách được liên kết trong ít hơn O (n)? Đó dường như là một vấn đề lớn.
Nick ODell

Bí quyết là chạy trên cả hai danh sách cùng một lúc. Bằng cách đó bạn có thể kiểm tra bất kỳ nhân đôi nào trong một lần quét.
Kris Van Bael

Sẽ không chèn đắt tiền bằng cách sử dụng một danh sách được sắp xếp? Một cây hoặc băm sẽ hoạt động tốt hơn.
kevin cline

Một cái cây thực sự có thể tốt hơn. Nhưng dù bằng cách nào, việc chèn được tối ưu hóa bằng cách có tất cả các kết nối của một nút được sắp xếp trước.
Kris Van Bael

Hay đúng hơn ... Danh sách liên kết đơn là hoàn toàn tốt. Xem các chỉnh sửa của câu trả lời.
Kris Van Bael

2

Chỉ cần sử dụng tìm kiếm hơi thở đầu tiên (không cần alg của Dijkstra vì tất cả các cạnh đều có chiều dài đồng đều) (và như Kris Van Bael đã nói, hãy chạy nó từ cả hai phía)


0

"All edges have a length of 1"Đây là một tình huống tốt nhất làm cho Thuật toán của Dijkstra trở thành một lựa chọn thuật toán tham lam hoàn hảo. Ngay cả khi sử dụng thuật toán Floyd-Warshall liên quan đến nhân ma trận nhanh cũng sẽ hoạt động tốt.


Tôi bối rối. Từ liên kết bạn đưa ra, có vẻ như thuật toán Floyd-Warshall nhằm mục đích giải quyết vấn đề đường đi ngắn nhất của tất cả các cặp. Có phải đó cũng là cách tốt nhất để tìm khoảng cách giữa một cặp?
Nick ODell

@NickODell Floyd-Warshall là một thuật toán tham lam để tìm các đường dẫn ngắn nhất trong biểu đồ. Nó chỉ là một, bao gồm Dijkstra khá phổ biến, để tìm các đường dẫn ngắn nhất từ ​​nút bắt đầu đến tất cả các nút khác. Hãy nhớ rằng, bạn đang tìm đường đi ngắn nhất từ ​​một nút được chỉ định đến tất cả các nút khác chứ không chỉ hai điểm.
Nấm
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.