Thuật toán tìm số đường dẫn đơn giản từ


34

Cần bất cứ ai đề nghị tôi một thuật toán thời gian tuyến tính mà có như là đầu vào một đạo acyclic graph và hai đỉnh và và trả về số lượng các đường dẫn đơn giản từ đến trong . Tôi có một thuật toán trong đó tôi sẽ chạy một DFS (Depth First Search) nhưng nếu DFS thấy thì nó sẽ không thay đổi màu sắc (từ màu trắng sang màu xám) của bất kỳ của các nút mà đi kèm trong đường dẫn để nếu đây là đường dẫn phụ của bất kỳ đường dẫn nào khác thì DFS cũng đi qua đường dẫn phụ này một lần nữa. Ví dụ, hãy xem xét danh sách kề, nơi chúng ta cần tìm số đường dẫn từ p đến v .s t s t G t s t p v p o s z o r s v s r r y y v v w zG=(V,E)ststG
tstpv

poszorsvsrryyvvwzwz
Ở đây DFS sẽ bắt đầu với p và sau đó giả sử nó đi đến pz vì nó không gặp v DFS sẽ chạy bình thường. con đường là psryv vì nó gặp phải v chúng tôi sẽ không thay đổi màu sắc của đỉnh s,r,y,v để grey.Then con đường pov từ màu sắc của v vẫn là white.Then con đường posryv từ màu sắc của s là màu trắng và tương tự của đường dẫn poryv.Cũng một bộ đếm được duy trì tăng lên khi gặp v .

Thuật toán của tôi có đúng không? nếu không, những sửa đổi nào là cần thiết để làm cho nó chính xác hoặc bất kỳ phương pháp tiếp cận nào khác sẽ được đánh giá cao.

Lưu ý : Ở đây tôi đã xem xét thuật toán DFS được đưa ra trong cuốn sách "Giới thiệu về thuật toán của Cormen", trong đó nó tô màu các nút theo trạng thái của nó. Vì vậy, nếu nút không được chú ý, không được khám phá và khám phá thì màu sẽ là màu trắng, màu xám và đen tương ứng. Tất cả những thứ khác là tiêu chuẩn.



4
Lưu ý rằng tất cả các đường dẫn trong biểu đồ chu kỳ có hướng đều nhất thiết phải đơn giản (nhờ tính chu kỳ).
Noldorin

Câu trả lời:


37

Việc triển khai hiện tại của bạn sẽ tính toán số lượng đường dẫn chính xác trong DAG. Tuy nhiên, bằng cách không đánh dấu đường dẫn, nó sẽ mất thời gian theo cấp số nhân. Ví dụ, trong hình minh họa bên dưới, mỗi giai đoạn của DAG tăng tổng số đường dẫn lên bội số 3. Sự tăng trưởng theo cấp số nhân này có thể được xử lý bằng lập trình động.

dag

Việc tính toán số lượng đường dẫn - trong DAG được đưa ra theo định kỳ, St

Paths(u)={1if u=t(u,v)EPaths(v)otherwise.

Một sửa đổi đơn giản của DFS sẽ tính toán điều này được đưa ra là

def dfs(u, t):
    if u == t:
        return 1
    else:
        if not u.npaths:
            # assume sum returns 0 if u has no children
            u.npaths = sum(dfs(c, t) for c in u.children)
        return u.npaths

Không khó để thấy rằng mỗi cạnh chỉ được nhìn một lần, do đó thời gian chạy của .O(V+E)


Tôi hiểu thuật toán của bạn và nó có thể được thực hiện hiệu quả hơn một chút bằng cách sử dụng lập trình động do các cuộc gọi đệ quy tương tự được gọi nhiều lần để tiết kiệm tốt hơn.
Saurabh

1
utu

1
Đối với các biểu đồ như vậy, không phải là câu trả lời chỉ m ^ n trong đó m là số nút trong một cột (3 ở đây) và n là số cột không bao gồm s, t (4 ở đây). đầu ra là 3 ^ 4 = 81 cho biểu đồ ví dụ.
saadtaame

@saadtaame, chắc chắn rồi; tuy nhiên, ý định của tôi chỉ đơn thuần là thể hiện sự gia tăng theo cấp số nhân khi "chiều dài" của đồ thị tăng lên. Tất nhiên đối với biểu đồ có cấu trúc cao đó, bạn có thể đếm ở dạng đóng trong khi thuật toán được liệt kê hoạt động cho tất cả các biểu đồ.
Nicholas Mancuso

3
Ôi(V+E)Θ(V)Ôi(VE)

15

Bạn chỉ cần lưu ý rằng số lượng đường dẫn từ một nút đến nút đích là tổng số lượng đường dẫn từ con của nó đến đích. Bạn biết rằng thuật toán này sẽ luôn dừng vì đồ thị của bạn không có chu kỳ.

Bây giờ, nếu bạn lưu số lượng đường dẫn từ một nút đến mục tiêu khi bạn truy cập vào các nút, thì độ phức tạp thời gian sẽ trở thành tuyến tính theo số lượng đỉnh và tuyến tính bộ nhớ trong số lượng nút.


0

Số lượng đường dẫn giữa hai đỉnh bất kỳ trong DAG có thể được tìm thấy bằng cách sử dụng biểu diễn ma trận kề.

Giả sử A là ma trận kề của G. Lấy sức mạnh thứ K của A sau khi thêm ma trận danh tính vào nó, đưa ra số lượng đường dẫn có độ dài <= K.

Vì độ dài tối đa của bất kỳ đường dẫn đơn giản nào trong DAG là | V | -1, tính toán sức mạnh | V | -1 sẽ cho số lượng đường đi giữa tất cả các cặp đỉnh.

Tính toán sức mạnh | V | -1 có thể được thực hiện bằng cách thực hiện các phép tính log (| V | -1) mỗi TC: | V | ^ 2.


Câu hỏi yêu cầu một thuật toán thời gian tuyến tính. Thuật toán của bạn chậm hơn thế.
DW

@Vivek bạn có thể đề cập đến một tài liệu tham khảo cho các định lý trong câu trả lời của bạn?
Hamideh
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.