Đường dẫn ngắn nhất đi qua (các) nút cụ thể


8

Tôi đang cố gắng tìm một giải pháp hiệu quả cho vấn đề của mình. Giả sử rằng tôi có đồ thị có trọng số dương Gchứa 100 nút (mỗi nút được đánh số) và đó là đồ thị theo chu kỳ. Vì vậy, không thể có bất kỳ cạnh như 2,2 hoặc 2,1. Tôi đã có một danh sách các nút giả sử 10 từ biểu đồ G. Giả sử mỗi nút này cũng nằm trong một mảng. Tôi đang tìm cách để tìm tổng trọng lượng của đường dẫn ngắn nhất từ ​​nút 1 đến 100 đi qua ít nhất một số cụ thể (giả sử 5) trong số các nút đó từ danh sách đó.

Để đơn giản hóa nó, hãy xem xét biểu đồ có 6 nút, 0 ... 5, bây giờ nút 1 và 4 được đánh dấu là các điểm mà chúng ta có thể chỉ định để vượt qua. Giả sử các đường dẫn hiện có là 0-1-2-5, 0-3-4-5 và 1-4. Bây giờ, giả sử tất cả các cạnh có trọng số là 5 ngoại trừ 3 đến 4 có trọng số là 1. Nếu chúng ta chạy một thuật toán đường đi ngắn nhất thì về cơ bản nó sẽ tìm thấy đường dẫn 0-3-4-5 vì nó có trọng số 11. Tuy nhiên nếu chúng ta chạy một thuật toán chỉ định số lượng tối thiểu của các điểm được chỉ định và thử số lượng 2. Sau đó, thuật toán sẽ được chạy vào 0-1-4-5, trọng số là 15.

Tôi đã viết theo cách này

    shortestPath(destinationNode, minAmount) 

        if(destinationNode == srcNode && minAmount < 1) 
            return 0

        else if(destinationNode == srcNode && minAmount > 1) 
            return INFINITY

        int destNo = destinationNode get number
        int cost = INFINITY
        for (int i = 0; i < destNo; i++)
            if (d[i][destNo] != null) 
                int minimumAmountCount = minAmount;
                for (int j = 0; j < marked.length(); j++) 
                    if (marked[j] == i) 
                        minimumAmountCount = minimumAmountCount - 1;

                cost = MIN(cost, shortestPath(Node(i), minimumAmountCount);

        return cost;

Về cơ bản, chúng tôi gọi thuật toán này bằng cách sử dụng nút đích và số lượng nút tối thiểu từ danh sách đó. Đầu tiên chúng tôi muốn đảm bảo rằng đây là một hàm đệ quy và nó phải có điểm dừng, sẽ là khi điểm đến được truyền bằng với nút nguồn (về cơ bản là nút # 0). Trường hợp thứ hai chúng ta cần kiểm tra là liệu chúng ta đã truy cập đủ số lượng chưa, vì vậy nếu nó nhỏ hơn 1 (0 hoặc số âm) thì chúng ta đã truy cập đủ điểm và trả về 0 vì khoảng cách từ nút # 0 đến nút # 0 sẽ là 0. Nếu chúng tôi đã không truy cập đủ số lượng sau đó chúng tôi trả lại vô hạn để thuật toán sẽ xem xét các đường dẫn khác.

Vì vậy, để phần trả về hoạt động, chúng ta phải xác định số của nút đích (nếu chúng ta nghĩ rằng chúng ta có 100 nút thì đó sẽ là nút số 99 khi bắt đầu ban đầu) và chi phí ban đầu là vô cùng.

Sau đó, chúng tôi chạy một vòng lặp for bắt đầu từ 0 (về cơ bản là nút số 0) cho đến số nút hiện tại của chúng tôi, điều này là do không có các cạnh ngược trên biểu đồ. Bằng cách sử dụng số nút, chúng tôi kiểm tra từ ma trận xem có trọng số hiện có cho các nút đó không. Nếu nó tồn tại thì chúng tôi khởi tạo một biến cho số tiền tối thiểu hiện tại của chúng tôi và sau đó chạy một vòng lặp và kiểm tra xem nguồn đến đích hiện tại có trong danh sách các nút được đánh dấu hay không. Nếu nó được đánh dấu thì chúng tôi chỉ cần giảm số tiền tối thiểu.

Đối với bước cuối cùng, chúng tôi chạy lại chức năng bằng cách thay đổi đích là nguồn hiện tại và với số tiền tối thiểu hiện tại.

Nhưng nó có vẻ rất tốn kém, vì thực tế là sự phức tạp tồi tệ nhất của vòng lặp lồng nhau chiếm O (| Node | ^ 2) và tổng số lần tái phát sẽ mất O (| Node | ^ 2 * | Edges |). Vì vậy, có bất kỳ giải pháp hiệu quả khác cho vấn đề này?


Bạn có thể giải thích thuật toán của bạn bằng lời?
Yuval Filmus

@YuvalFilmus Tôi đã làm nó bây giờ.
Sarp Kaya

Câu trả lời:


2

Tính toán đường đi ngắn nhất giữa tất cả các cặp của mười hai nút đặc biệt (các nút 1, 100 và tất cả mười nút cụ thể của bạn) và sử dụng chúng làm độ dài cạnh trong biểu đồ mới chỉ bao gồm mười hai nút này. Bây giờ, bạn có một biểu đồ chứa mười hai nút và bạn muốn tìm đường dẫn ngắn nhất từ ​​1 đến 100 sử dụng ít nhất năm nút khác. Bây giờ, bạn có thể sử dụng thuật toán của mình (mà tôi nghĩ chỉ là lập trình động) trên biểu đồ này, nhỏ hơn nhiều. Giải pháp trên biểu đồ mới sẽ đưa ra giải pháp cho biểu đồ gốc mà bạn có thể tìm thấy bằng cách thay thế các cạnh trong giải pháp trong biểu đồ mới bằng các đường dẫn ngắn nhất bạn đã tính trong bước đầu tiên.

Ví dụ của bạn, chúng tôi sẽ có 4 nút trong biểu đồ mới. Độ dài cạnh trong biểu đồ mới là: 0-1: 5, 0-4: 6, 0-5: 11, 1-4: 5, 1-5: 10, 4-5: 5. Chúng tương ứng với các đường dẫn ngắn nhất giữa các nútTôijtrong biểu đồ ban đầu. Đường dẫn ngắn nhất bao gồm một nút trong danh sách là 0-4-5, có độ dài 11. Bây giờ, thay thế mỗi cạnh trong đường dẫn này bằng đường dẫn được tính trong bước đầu tiên sẽ tạo đường dẫn 0-3-4-5 trong bản gốc đồ thị.


Không không ít nhất năm nút khác. Giả sửN là tất cả các nút, LN Trong đó L là danh sách các nút và |P|<=|L|ở đâu | P | là số lượng điểm tối thiểu mà đồ thị nên được xây dựng. Nội dung của P được lấy từ L vì nó sử dụng lượng tối thiểu (| P |) của các phần tử L. Vì vậy, có ít nhất năm nút trong danh sách 10
Sarp Kaya

Tôi đã thêm một ví dụ trong câu hỏi của tôi, bạn có thể vui lòng kiểm tra nó?
Sarp Kaya

Nhưng trong biểu đồ mới, bên cạnh các nút bắt đầu và kết thúc, chỉ có mười nút đó.
Peter Shor

1
Tôi đang nói, hãy bắt đầu với biểu đồ ban đầu của bạn, sau đó xây dựng một biểu đồ mới. Giải quyết vấn đề đã sửa đổi trên biểu đồ mới, sau đó chuyển giải pháp trở lại biểu đồ ban đầu. Biểu đồ mới chỉ chứa 12 nút. Khoảng cách trong biểu đồ mới tương ứng với các đường dẫn ngắn nhất giữa các nút được chọn trong biểu đồ ban đầu.
Peter Shor

2
Tôi không dự định. Nếu ai đó muốn đưa ra giải pháp của tôi và viết một câu trả lời khác giải thích nó bằng mã giả, họ sẽ cảm thấy thoải mái để tiếp tục.
Peter Shor

0

Nếu tất cả những gì bạn có là 100 nút và cung của bạn được cung cấp hoặc dễ dàng tính toán: đừng lo lắng về điều đó.

Nếu không: biểu đồ của bạn có thể rất thưa thớt (nhiều cặp nút có cung hơn là không có cung). Vì vậy, sử dụng danh sách được liên kết hoặc một số cấu trúc dữ liệu khác cho phép bạn lặp qua chỉ các cung, không phải bỏ qua các cung không phải. Tên của các cấu trúc dữ liệu đó phụ thuộc vào ngôn ngữ; Các loại khác nhau của chất lượng Danh sách hoặc Từ điển Java hoặc C #, ví dụ như băm trong Perl hoặc mảng kết hợp trong PHP.

Tôi sẽ sử dụng chúng để xây dựng ánh xạ từ các nút để chuyển tiếp các cung (tức là các cặp nút chi phí và nút đích) và một nút khác từ các nút đến các cung ngược.

Tôi sẽ phân bổ thêm hai để giữ khoảng cách giữa các nút từ mỗi nút đến từng nút trung gian và từ mỗi nút trung gian đến mỗi nút và tính toán chúng bằng thuật toán tiêu chuẩn (Floyd, còn được gọi là Dijkstra, hoặc, nhầm, , Warshall's).

Tôi sẽ phân bổ thêm một lần nữa để giữ khoảng cách giữa các nút cuối cùng và tính toán chúng như là

d(x,y)= =mTôinzTôi(d(x,z)+d(z,y))
cho các nút trung gian Tôi.

Tôi không có 100 nút, tôi chỉ muốn đưa ra một số ví dụ. Bạn có thể giải thích các câu của bạn bằng cách sử dụng ngôn ngữ pseudocode hoặc java / C ++ không?
Sarp Kaya

Tôi quá lười. Lấy làm tiếc.
Revierpost
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.