2013-12-12 69 views
5

Tôi phải đảm bảo rằng biểu đồ trong ứng dụng của chúng tôi là một DAG với nguồn duy nhất và bồn rửa độc đáo. Cụ thể, tôi phải đảm bảo rằng đối với một nút bắt đầu và nút kết thúc (cả hai đều được biết ngay từ đầu) rằng mọi nút trong biểu đồ nằm trên một đường dẫn từ nút bắt đầu đến nút kết thúc.DAG - Thuật toán để đảm bảo có một nguồn duy nhất và một bồn rửa đơn

Tôi đã thực hiện thuật toán Tarjan mà tôi sử dụng để xác định chu kỳ và thuật toán phân loại topo mà tôi có thể chạy khi thuật toán của Tarjan báo cáo biểu đồ là DAG.

Cách hiệu quả nhất để đảm bảo biểu đồ đáp ứng tiêu chí này là gì?

+0

Tìm các thành phần được kết nối mạnh mẽ. Sau đó, bạn có CC nguồn và chìm CC. Kiểm tra xem cả hai chỉ chứa một phần tử. Độ phức tạp cũng là tuyến tính. –

+0

Trên thực tế, không phải thuật toán của Tarjan là thuật toán tìm thấy thành phần được kết nối mạnh mẽ? –

Trả lời

1

Nếu biểu đồ của bạn được biểu diễn bằng ma trận kề, thì nút x là nút nguồn nếu cột x của ma trận là 0 và là nút chìm nếu hàng x của ma trận bằng 0. Bạn có thể chạy hai đường nhanh trên ma trận để đếm số hàng và cột là 0 để xác định có bao nhiêu nguồn và bồn tồn tại và chúng là gì. Điều này cần có thời gian O (n) và có lẽ là cách nhanh nhất để kiểm tra điều này.

Nếu biểu đồ của bạn được đại diện bởi danh sách kề, bạn có thể tìm tất cả các nút chìm trong thời gian O (n) bằng cách kiểm tra xem có nút nào không có cạnh ngoài. Bạn có thể tìm thấy tất cả các bồn bằng cách duy trì cho mỗi nút một giá trị boolean cho biết liệu nó có bất kỳ cạnh đến nào không, ban đầu là sai. Sau đó bạn có thể lặp qua tất cả các cạnh trong danh sách trong thời gian O (n + m) đánh dấu tất cả các nút có các cạnh đến. Các nút không được đánh dấu là có các cạnh đến sau đó là các nguồn. Quá trình này cần có thời gian O (m + n) và có ít chi phí như vậy mà nó có lẽ là một trong những cách tiếp cận nhanh nhất.

Hy vọng điều này sẽ hữu ích!

+0

bạn gần như chính xác, nhưng vẫn cần phải có một BFS hoặc tương tự để kiểm tra xem tất cả các nút có thể đạt đến bồn rửa, như đồ thị có thể chứa chu kỳ :) –

+0

@ PhamTrung- Đó là sự thật. Tôi giả sử đồ thị được biết là một DAG. – templatetypedef

+0

Tất cả giả sử có một số ma trận kề cận kề hoặc danh sách. Có gì là không và bạn đang khám phá các nút trong khi đi ngang qua. Bạn có cần cách tiếp cận khác không? – alex

0

Tìm kiếm có chiều rộng hoặc chiều sâu đơn giản nên thỏa mãn điều này. Thứ nhất, bạn có thể giữ một tập hợp các nút bao gồm các nút chìm mà bạn đã thấy. Thứ hai, bạn có thể giữ một tập hợp các nút mà bạn đã phát hiện bằng BFS/DFS. Sau đó, biểu đồ sau đó sẽ được kết nối với iff có một thành phần được kết nối duy nhất. Giả sử bạn đang sử dụng một số loại đại diện danh sách kề kề cho biểu đồ của mình, thuật toán sẽ trông giống như sau:

create an empty queue 
create an empty set to store seen vertices 
create an empty set for sink nodes 

add source node to queue 

while queue is not empty 
    get next vertex from queue, add vertex to seen vertices 
    if num of adjacent nodes == 0 
     add sink nodes to sink node set 
    else 
     for each node in adjacent nodes 
     if node is not in seen vertices 
      add node to queue 

return size of sink nodes == 1 && size of seen vertices == total number in graph 

Điều này sẽ tuyến tính theo số đỉnh và cạnh trong biểu đồ.

Lưu ý rằng miễn là bạn biết một đỉnh nguồn để bắt đầu, điều này cũng sẽ đảm bảo tài sản của một nguồn duy nhất: bất kỳ đỉnh nào khác là nguồn sẽ không được BFS/DFS phát hiện và kích thước của các đỉnh được nhìn thấy sẽ không là tổng số trong biểu đồ.

0

Nếu thuật toán của bạn lấy đầu vào là DAG, kết nối yếu, giả sử chỉ có một nút có độ trong bằng 0 và chỉ một nút t có độ lệch bằng 0, trong khi tất cả các nút khác có kết quả dương ở mức độ và mức độ, sau đó s có thể đạt được tất cả các nút khác, và tất cả các nút khác có thể đạt tới t. Theo mâu thuẫn, giả sử rằng có một nút v mà s không thể tiếp cận được. Vì không có nút nào có thể đạt được s, tức là, v không thể đạt tới s. Như vậy, v và s bị ngắt kết nối, điều này mâu thuẫn với giả định. Mặt khác, nếu DAG không được kết nối yếu, nó chắc chắn không đáp ứng các yêu cầu mà bạn muốn. Tóm lại, trước tiên bạn có thể tính toán thành phần yếu được kết nối của DAG chỉ đơn giản bằng cách sử dụng BFS/DFS, trong khi đó ghi nhớ số lượng các nút có độ trong hoặc ngoài là bằng không. Độ phức tạp của thuật toán này là O (| E |).

0

Trước tiên, hãy thực hiện DFS trên biểu đồ, bắt đầu từ nút nguồn, như bạn đã biết, được biết trước. Nếu bạn gặp phải một cạnh sau [1], sau đó bạn có một chu kỳ và bạn có thể thoát ra với một lỗi.Trong quá trình truyền tải này, bạn có thể xác định nếu có các nút, không thể truy cập từ nguồn [2] và thực hiện hành động thích hợp.

Một khi bạn đã xác định đồ thị là một DAG, bạn có thể đảm bảo rằng tất cả các nút nằm trên một đường đi từ nguồn đến chìm bởi một DFS, bắt đầu từ nguồn, như sau:

bool have_path(source, sink) { 
    if source == sink { 
     source.flag = true 
     return true 
    } 

    // traverse all successor nodes of `source` 
    for dst in succ(source) { 
     if not dst.flag and not have_path(dst, sink) 
      return false // exit as soon as we find a node with no path to `sink` 
    } 
    source.flag = true; 
    return true 
} 

Các thủ tục have_path thiết lập một boolean flag trong mỗi nút, trong đó có tồn tại một số đường dẫn từ nút đó đến bồn rửa. Trong cùng một thời gian, thủ tục chỉ duyệt qua các nút có thể truy cập từ nguồn và nó đi qua tất cả các nút có thể truy cập từ nguồn. Nếu thủ tục trả về true, thì tất cả các nút, có thể truy cập từ nguồn nằm trên một đường dẫn đến bồn rửa. Các nút không thể truy cập đã được xử lý trong giai đoạn đầu tiên.


[1] một cạnh, liên kết một nút với một số DFS lớn hơn cho một nút với một số DFS thấp hơn, đó không phải là đã hoàn toàn xử lý, tức là vẫn còn trên DFS chồng

[2 ] ví dụ họ sẽ không có số DFS được chỉ định

Các vấn đề liên quan