Như Yuval đề cập, cơ sở hạ tầng rất quan trọng ở đây. Tôi sẽ cố gắng đưa ra giải pháp cho một số loại danh sách kề:
- Danh sách cạnh đến : Đối với mỗi nút, có một danh sách các đỉnh mà từ đó có một cạnh đến nút này. Bạn có thể chỉ cần quét tất cả các đỉnh và kiểm tra xem kích thước của danh sách kề của chúng có bằng hay không. Danh sách kích thước 0 có nghĩa là không có cạnh đến, vì vậy nút là nguồn hoặc bị ngắt kết nối. Giả sử một đồ thị được kết nối, quá trình quét từng đỉnh này sẽ cung cấp cho bạn một danh sách tất cả các nguồn (hoặc bạn có thể dừng sau khi tìm thấy một) trong thời gian O ( | V | ) - tuyến tính theo số lượng đỉnh .00O(|V|)
- Danh sách cạnh đi : Đối với mỗi nút, có một danh sách các đỉnh có cạnh được định hướng từ nút này. Giữ một chuỗi bit với mỗi bit đại diện cho một đỉnh, được khởi tạo thành 0. Bắt đầu từ nút đầu tiên, bắt đầu quét danh sách của nó cho các đỉnh có cạnh đi ra từ đây. Mỗi nút như vậy (lân cận) không thể là một nguồn, vì vậy hãy tiếp tục đặt bit tương ứng của chúng trong chuỗi bit. Cuối cùng, tất cả các đỉnh có bit tương ứng vẫn chưa được đặt, là các đỉnh nguồn. Bạn có thể làm điều này theo thời gian tuyến tính theo kích thước của biểu đồ - .O(|V|+|E|)
- Cả hai danh sách cùng nhau : Đối với mỗi đỉnh, có một danh sách hỗn hợp các đỉnh có cạnh đến hoặc từ đỉnh này, với một số thuộc tính khác cho biết trường hợp nào trong hai đỉnh thực sự là trường hợp. Cách tiếp cận tương tự như 2 ở trên, với sự bổ sung rằng bất kỳ cạnh đến nào cũng ngay lập tức loại bỏ đỉnh hiện tại (và bạn có thể đánh dấu tập bit của nó). Không giống như ở điểm 2 nơi bạn cần đi qua tất cả các đỉnh, ở đây, bạn có thể tìm thấy một số nguồn sớm hơn. Nếu bạn không dừng lại, bạn sẽ có tất cả các nguồn. Đối với cả hai trường hợp, thời gian lại là tuyến tính theo kích thước của biểu đồ - .O(|V|+|E|)
- Cả hai danh sách riêng biệt : Chỉ cần chọn danh sách cạnh đến và làm theo 1.
Một lưu ý phụ, nếu chọn cơ sở hạ tầng nằm trong tay bạn, bạn có thể muốn phân tích tất cả các hoạt động bạn định thực hiện và tần suất và chọn cơ sở hạ tầng phù hợp.
Chỉnh sửa: Đối với trường hợp 1, nếu bạn có một dag trong đó số lượng nguồn rất nhỏ so với (ví dụ: trong một cây có một nguồn) và trong đó khoảng cách trung bình từ bất kỳ đỉnh nào đến một nguồn nhỏ so với | V | và bạn chỉ muốn bất kỳ một nguồn nào, bạn có thể sử dụng thuật toán trung bình nhanh hơn (mặc dù trường hợp phức tạp tiệm cận tồi tệ nhất sẽ giống nhau). Chọn bất kỳ đỉnh nào một cách ngẫu nhiên và đi đến bất kỳ cha mẹ nào của nó (từ danh sách cạnh đến) và tiếp tục với cha mẹ của nó, cho đến khi bạn đến một nút không có cha mẹ - một nguồn. Mức tăng hiệu quả nhỏ này dành cho các loại biểu đồ rất hạn chế với thuật toán phức tạp hơn một chút.|V||V|