Làm thế nào để tìm một siêu sao trong thời gian tuyến tính?


28

Hãy xem xét các đồ thị có hướng. Chúng ta gọi một siêu sao nút khi và chỉ khi không có nút nào khác có thể đạt được từ nó, nhưng tất cả các nút khác có cạnh với . Chính thức:v v

v siêu sao : ⟺obạntdeg(v)= =0tôindeg(v)= =n-1

với số lượng nút trong biểu đồ. Ví dụ, trong biểu đồ bên dưới, nút không được lấp đầy là một siêu sao (và các nút khác thì không).n

Một siêu sao
[ nguồn ]

Làm thế nào bạn có thể xác định tất cả các siêu sao trong một biểu đồ có hướng trong thời gian Ôi(n) ? Một đại diện đồ thị phù hợp có thể được chọn từ các ứng cử viên thông thường ; vui lòng không sử dụng các biểu diễn chuyển sự phức tạp của vấn đề sang tiền xử lý.

Không có giả định về mật độ có thể được thực hiện. Chúng tôi không cho rằng biểu đồ chứa một siêu sao; nếu không có, thuật toán sẽ nhận ra nó.

Ký hiệu : outdeg là số cạnh của nút đi, indeg tương tự cho các cạnh đến.


1
Chúng ta có cho phép trong đó là các cạnh hay chúng ta chỉ cần nhìn vào các cạnh trên mỗi đỉnh? O(n+k)kO(1)
Kevin

@Kevin Không, là một yêu cầu nghiêm ngặt. Về câu hỏi thứ hai: Tôi thậm chí không biết điều đó là cần thiết, nhưng bạn chắc chắn không thể làm gì hơn. O(n)
Raphael

Bạn có biết câu trả lời không? Nó có thể được thực hiện trong không? O(n)
Dave Clarke

@DaveClarke: Vâng, và vâng.
Raphael

Bạn nên hạn chế đại diện hơn nữa; một thuật toán tuyến tính là không thể đối với một danh sách kề (chỉ cần xác nhận rằng một đỉnh là một siêu sao, bạn có thể cần phải đi qua toàn bộ danh sách ở mỗi đỉnh).
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


18

Chúng ta có thể loại bỏ tất cả trừ một trong các đỉnh bằng cách kiểm tra sự tồn tại của cạnh vì chúng ta có thể loại bỏ một khả năng cho mỗi cạnh mà chúng ta kiểm tra. Cụ thể, nếu có một cạnh đi từ x đến y , chúng ta loại bỏ x và chuyển sang y (vì một đỉnh khác có thể đạt được từ nó); nếu không, chúng ta loại bỏ y (vì nó không thể đạt được từ x ). Khi chúng ta đạt đến đỉnh cuối cùng, bất kỳ đỉnh nào không bị loại bỏ nên được so sánh với các đỉnh khác (đảm bảo điều kiện siêu sao được duy trì: có một cạnh đến nhưng không đi ra ngoài) cho đến khi nó bị loại bỏ hoặc được xác nhận là siêu sao. Một số mã giả:n-1xyxyyx

vertex superstar(graph g)
    current vertex = first
    # Go through each vertex
    for each subsequent vertex in g ("next")
        # If there's an edge from this to the next, we eliminate this one [move to the new one].
        # If not, we just stay here.
        if edge exists from current to next
            candidate = next
        end if
    end for
    # Now we are on the final remaining candidate, check whether it satisfies the requirements.
    # just a rename for clarity
    candidate = current
    for each other vertex in g
        if edge from current to other exists
            return null 
        else if no edge from other to current
            return null
        end if
    end for
    return candidate
end superstar

Chúng ta hãy đi qua một ví dụ để minh họa phương pháp. Lấy mảng này, với đỉnh nguồn ở trên cùng và đích ở bên cạnh. 1 chỉ ra một cạnh:

12341-10121-01311-14110-

Tôi sẽ loại bỏ các đỉnh mà chúng ta đã loại trừ như những siêu sao tiềm năng. Tôi sẽ sử dụng màu xanh lá cây và màu đỏ để chỉ ra các cạnh mà chúng ta đang nhìn khi chúng thực hiện và không chứa cạnh chúng ta đang tìm kiếm và màu xanh lam để chỉ ra nơi chúng ta đã nhìn.

Chúng ta bắt đầu bằng cách nhìn vào các đỉnh 1 và 2.

Số màu xanh lá cây cho thấy có một cạnh từ 2 đến 1, vì vậy chúng tôi loại bỏ 2 và tìm cạnh từ 3 đến 1 :

12341-10121-01311-14110-

12341-10121-01311-14110-

Chúng tôi thấy không có cạnh như vậy, vì vậy chúng tôi loại bỏ 1 và lấy 3 làm đỉnh hiện tại của chúng tôi. Hãy nhớ lại rằng chúng tôi đã loại bỏ 2, vì vậy hãy xem liệu có cạnh từ 4 đến 3 hay không:

12341-10121-01311-14110-

Có một cạnh từ 4 đến 3, vì vậy chúng tôi loại bỏ 4. Tại thời điểm này, chúng tôi đã loại bỏ tất cả trừ một trong các đỉnh (3), vì vậy hãy kiểm tra các cạnh của nó và xem liệu nó có đủ điều kiện không:

12341-10121-01311-14110-

Có một cạnh từ 1 đến 3 nhưng không phải là ngược lại, vì vậy 3 vẫn là một ứng cử viên.

12341-10121-01311-14110-

Ngoài ra còn có một cạnh từ 2 đến 3 nhưng không phải là ngược lại, vì vậy 3 vẫn là một ứng cử viên.

12341-10121-01311-14110-

Có một cạnh từ 4 đến 3 nhưng không phải 3 đến 4; hoàn thành việc kiểm tra các cạnh của chúng tôi và chúng tôi đã thấy rằng trên thực tế, đó là một siêu sao.

n-1nnn-12×(n-1)3n-3Ôi(n)Θ(n)


8

Đây không phải là vấn đề của người nổi tiếng sao?

Sẽ chỉ có một siêu sao (người nổi tiếng) nếu có.

Một[tôi,j]= =1tôij0

Một[tôi,j]Ôi(1)Một[tôi,j]= =1tôiMột[tôi,j]= =0j

Duy trì một danh sách các ứng cử viên hiện tại, loại bỏ từng người một. Một danh sách liên kết nên đủ.

Cuối cùng, bạn có thể xác minh xem ứng cử viên của bạn có thực sự là một siêu sao hay không.

Ôi(n)


(tôi,j)

3
@Raphael: Chỉ cần chọn hai ứng cử viên đầu tiên từ danh sách được liên kết. (đầu và đầu-> tiếp theo).
Aryabhata

6

Câu trả lời này giải quyết phiên bản của câu hỏi trong đó bất kỳ biểu diễn đồ thị nào đều có thể, không phải là phiên bản hiện tại của câu hỏi.

  • Lưu trữ biểu đồ của bạn dưới dạng một cặp danh sách kề và danh sách kề kề, trong đó mỗi danh sách chứa thêm độ dài của danh sách, do đó lần lượt là các số ngoài và trong các cạnh.

  • Ôi(|E|)

  • 0n-1Ôi(|N|)


Ok, tôi thấy rằng cho phép bất kỳ biểu diễn đồ thị là quá yếu. Tôi giới hạn câu hỏi cho những gì tôi dự định.
Raphael

2

Chỉ để tham khảo, đây là mã giả của phiên bản đệ quy của những gì Kevin đã đăng.

superstar(V, E) {
  if ( |V| == 1 ) {
    return V.pop
  }

  a = V.pop
  b = V.pop
  if ( (a,b) ∈ E ) {
    no_ss = a
    keep  = b
  }
  else {
    no_ss = b
    keep = a
  }

  s = superstar(V ++ keep)

  return ( s != null && (no_ss, s) ∈ E && !(s, no_ss) ∈ E ) ? s : null
}

hasSuperstar(V, E) = superstar(V, E) != null
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.