ความจริงที่ว่ากราฟของเราเป็นแบบวนรอบทำให้ปัญหานี้ง่ายขึ้นมาก
การจัดเรียง topologicalสามารถให้เราสั่งของจุดเช่นว่าถ้าฉัน< Jแล้วมีขอบจากไม่มีวีเจกลับไปวีฉัน เราได้แสดงรายการจุดยอดที่ขอบทั้งหมดไปใน "ไปข้างหน้า" ในรายการของเราv1,v2,…,vni<jvjvi
(แก้ไขเพื่อแก้ไขการวิเคราะห์และให้อัลกอริทึมเร็วขึ้นเล็กน้อย)
ตอนนี้เราก็ย้อนกลับไปดูรายการนี้เริ่มต้นที่จุดสุดท้าย n การปิดสกรรมกริยาของv nเป็นเพียงตัวของมันเอง นอกจากนี้ยังเพิ่มV nเพื่อปิดสกรรมกริยาของทุกจุดสุดยอดกับขอบสระV nvnvnvnvn
สำหรับแต่ละจุดสุดยอดอื่น ๆไปจากที่สิ้นสุดหลังแรกเพิ่มโวลต์ฉันไปสู่การปิดสกรรมกริยาของตัวเองแล้วเพิ่มทุกอย่างในการปิดสกรรมกริยาของวีฉันจะปิดสกรรมกริยาของจุดทั้งหมดที่มีขอบสระโวฉันvivivivi
เวลาทำงานเป็นในกรณีที่เลวร้ายที่สุดที่มีnจำนวนจุดและม. ∈ O ( n 2 )จำนวนขอบ การจัดเรียง topological ต้องใช้เวลาO ( n + ม. ) จากนั้นเราก็ทำงานO ( m n ) อีกอันใน backward pass: เมื่อเราย้อนกลับไปตามรายการสำหรับแต่ละ edge เราต้องรวมกันเป็นnO(n+m+nm)=O(n3)nm∈O(n2)O(n+m)O(mn)n การปิดจุดยอดของใครบางคน
โปรดทราบว่าคุณสามารถเพิ่มความเร็วได้อย่างต่อเนื่องด้วยการแสดงการปิดบิตของอาร์เรย์ สมมติว่าคุณมีเพียง ; จากนั้นคุณจะใช้ int 64- บิตเดียวโดยที่ bit iคือ 1 ถ้าฉันอยู่ใน transitive closure และ 0 เป็นอย่างอื่น นั้นเป็นส่วนหนึ่งที่เราเพิ่มทุกอย่างในฉัน 'ปิดสกรรมกริยาเพื่อJ ' S มันอย่างรวดเร็ว: เราใช้เวลาเพียงแค่คเจ | = Cฉัน (ไบนารีหรือการดำเนินการ)n=64iiijcjci
สำหรับคุณจะต้องเก็บมันไว้ในอาร์เรย์และทำเลขคณิต แต่มันจะเร็วกว่าชุดวัตถุn>64
นอกจากนี้ฉันรู้ว่าตัวใหญ่ - ในกรณีที่เลวร้ายที่สุดคือยังคงเป็นO ( n 3 )แต่การเอาชนะสิ่งนี้ในทางปฏิบัติคุณต้องมีอะไรที่ซับซ้อนกว่านี้ อัลกอริทึมนี้ยังทำงานได้ดีบนกราฟกระจายOO(n3)