อัลกอริธึมที่ดีที่สุดสำหรับการตรวจจับรอบในกราฟกำกับ


396

อัลกอริธึมที่มีประสิทธิภาพที่สุดในการตรวจจับรอบทั้งหมดภายในกราฟที่กำกับคืออะไร?

ฉันมีกราฟกำกับที่แสดงถึงกำหนดการงานที่ต้องดำเนินการงานเป็นโหนดและการพึ่งพาเป็นขอบ ฉันต้องการตรวจสอบกรณีข้อผิดพลาดของวัฏจักรภายในกราฟนี้ซึ่งนำไปสู่การพึ่งพาแบบวนรอบ


13
คุณบอกว่าคุณต้องการตรวจจับทุกรอบ แต่กรณีใช้ของคุณแสดงว่าเพียงพอที่จะตรวจพบว่ามีรอบใดหรือไม่
Steve Jessop

29
มันจะดีกว่าที่จะตรวจสอบทุกรอบเพื่อให้พวกเขาสามารถได้รับการแก้ไขในครั้งเดียวมากกว่าตรวจสอบแก้ไขตรวจสอบแก้ไข ฯลฯ
Peauters

2
คุณควรอ่านกระดาษ "ค้นหาวงจรเบื้องต้นทั้งหมดของกราฟกำกับ" โดย Donald B. Johnson มันจะพบเฉพาะวงจรระดับประถมศึกษา แต่นี่น่าจะเพียงพอสำหรับกรณีของคุณ และนี่คือการนำ Java ของฉันไปใช้อัลกอริทึมนี้พร้อมใช้งาน: github.com/1123/johnson
user152468

รัน DFS ด้วยการแก้ไขเพิ่มเติมสำหรับอัลกอริทึม: ทำเครื่องหมายแต่ละโหนดที่คุณเยี่ยมชม ถ้าคุณไปที่โหนดที่มีการเยี่ยมชมแล้วคุณมี cicle เมื่อคุณถอยออกจากเส้นทางให้ทำเครื่องหมายที่โหนดที่เข้าชม
Hesham Yassin

2
@HeshamYassin ถ้าคุณไปที่โหนดที่คุณเคยเยี่ยมชมมันไม่ได้แปลว่ามีวงวน โปรดอ่านความคิดเห็นของฉันcs.stackexchange.com/questions/9676/...
Maksim Dmitriev

คำตอบ:


193

อัลกอริธึมการเชื่อมต่อที่รุนแรงของ TarjanมีO(|E| + |V|)ความซับซ้อนของเวลา

สำหรับอัลกอริทึมอื่น ๆ ให้ดูส่วนประกอบที่เชื่อมต่ออย่างมากใน Wikipedia


69
การค้นหาส่วนประกอบที่เชื่อมโยงอย่างมากจะบอกคุณเกี่ยวกับรอบที่มีอยู่ในกราฟได้อย่างไร
ปีเตอร์

4
อาจเป็นคนที่สามารถยืนยันได้ แต่อัลกอริทึม Tarjan ไม่สนับสนุนรอบของโหนดที่ชี้ไปยังตัวเองโดยตรงเช่น A-> A
Cédric Guillemette

24
@Cedrik ใช่ไม่ใช่โดยตรง นี่ไม่ใช่ข้อบกพร่องในอัลกอริทึมของ Tarjan แต่วิธีที่ใช้สำหรับคำถามนี้ Tarjan ไม่พบรอบโดยตรงแต่ก็พบว่ามีส่วนประกอบที่เชื่อมต่ออย่างมาก แน่นอนว่า SCC ใด ๆ ที่มีขนาดใหญ่กว่า 1 หมายถึงรอบ ส่วนประกอบที่ไม่เป็นวงจรมี SCC เดี่ยวในตัวเอง ปัญหาคือว่าการวนรอบตัวเองจะเข้าสู่ SCC ด้วยตัวเอง ดังนั้นคุณต้องตรวจสอบแยกต่างหากสำหรับการวนรอบตัวเองซึ่งค่อนข้างน่ารำคาญ
mgiuca

13
(ส่วนประกอบที่เชื่อมต่ออย่างยิ่งทั้งหมดในกราฟ)! = (วงจรทั้งหมดในกราฟ)
optimusfrenk

4
@ aku: สามสี DFS O(|E| + |V|)นอกจากนี้ยังมีรันไทม์เดียวกัน ใช้สีขาว (ไม่เคยเยี่ยมชม), สีเทา (โหนดปัจจุบันถูกเยี่ยมชม แต่โหนดที่เข้าถึงได้ทั้งหมดยังไม่ได้เยี่ยมชม) และสีดำ (โหนดที่เข้าถึงได้ทั้งหมดจะถูกเยี่ยมชมพร้อมกับโหนดปัจจุบัน) การเข้ารหัสสีหากโหนดสีเทาพบโหนดสีเทาอื่น มีรอบ [ค่อนข้างดีสิ่งที่เราอยู่ในหนังสืออัลกอริทึมของ Cormen] สงสัยว่า 'อัลกอริทึมของ Tarjan' มีประโยชน์มากกว่า DFS เช่นนี้หรือไม่ !!
KGhatak

73

ระบุว่านี่เป็นตารางเวลาของงานฉันสงสัยว่าในบางจุดคุณจะเรียงลำดับงานตามคำสั่งที่เสนอ

หากเป็นเช่นนั้นการดำเนินการจัดเรียงโทโพโลยีอาจในกรณีใด ๆ ที่ตรวจพบรอบ ยูนิกซ์ทำtsortอย่างแน่นอน ฉันคิดว่ามันเป็นไปได้ที่จะมีประสิทธิภาพมากขึ้นในการตรวจสอบรอบในเวลาเดียวกันกับการคัดแยกมากกว่าในขั้นตอนที่แยกต่างหาก

ดังนั้นคำถามอาจกลายเป็น "ฉันจะส่งผลอย่างมีประสิทธิภาพมากที่สุด" ได้อย่างไรแทนที่จะเป็น "ฉันจะตรวจจับลูปได้อย่างมีประสิทธิภาพมากที่สุด" ได้อย่างไร คำตอบที่น่าจะเป็น "ใช้ห้องสมุด" แต่ล้มเหลวที่บทความ Wikipedia ดังต่อไปนี้:

http://en.wikipedia.org/wiki/Topological_sorting

มีโค้ดหลอกสำหรับอัลกอริทึมหนึ่งและคำอธิบายสั้น ๆ ของอีกอันจาก Tarjan ทั้งสองมีO(|V| + |E|)ความซับซ้อนของเวลา


การเรียงลำดับโทโพโลยีสามารถตรวจจับรอบได้ซึ่งขึ้นอยู่กับอัลกอริทึมการค้นหาขั้นแรก แต่คุณต้องมีการทำบัญชีเพิ่มเติมเพื่อตรวจจับรอบจริง ดูคำตอบที่ถูกต้องของ Kurt Peek
ลุคฮัทชิสัน

33

วิธีที่ง่ายที่สุดที่จะทำก็คือการทำลึกสำรวจเส้นทางแรก (DFT) ของกราฟ

หากกราฟมีnจุดยอดนี่เป็นO(n)ขั้นตอนวิธีความซับซ้อนของเวลา O(n^2)เนื่องจากคุณอาจจะต้องทำผิวเผินเริ่มต้นจากจุดสุดยอดแต่ละความซับซ้อนทั้งหมดจะกลายเป็น

คุณต้องรักษาสแต็คที่มีจุดยอดทั้งหมดในความลึกของการสำรวจเส้นทางแรกด้วยองค์ประกอบแรกที่เป็นโหนดรูต หากคุณเจอองค์ประกอบที่มีอยู่แล้วในสแต็กระหว่าง DFT แสดงว่าคุณมีรอบ


21
นี่จะเป็นจริงสำหรับกราฟ "ปกติ" แต่เป็นเท็จสำหรับกราฟกำกับ ตัวอย่างเช่นให้พิจารณา "ไดอะแกรมการพึ่งพาเพชร" ที่มีสี่โหนด: A ที่มีขอบที่ชี้ไปที่ B และ C ซึ่งแต่ละอันมีขอบที่ชี้ไปที่ D การสำรวจเส้นทาง DFT ของคุณจาก A นี้จะสรุปได้อย่างไม่ถูกต้องว่า จริง ๆ แล้วเป็นวัฏจักร - ถึงแม้จะมีการวนซ้ำมันไม่ใช่วัฏจักรเพราะมันไม่สามารถเคลื่อนที่ได้โดยทำตามลูกศร
ปีเตอร์

9
@ กรุณาช่วยอธิบายว่า DFT จาก A จะสรุปได้อย่างไม่ถูกต้องว่ามีรอบอย่างไร
Deepak

10
@Deepak - ในความเป็นจริงฉันเข้าใจผิดคำตอบจาก "ตัวช่วยสร้าง phys": ที่เขาเขียน "ในกอง" ฉันคิดว่า "ได้พบแล้ว" แน่นอนว่ามันจะเพียงพอ (สำหรับการตรวจจับลูปกำกับ) เพื่อตรวจสอบการ "ในกองซ้อน" ในระหว่างการดำเนินการ DFT หนึ่งโหวตสำหรับคุณแต่ละคน
ปีเตอร์

2
ทำไมคุณถึงบอกว่าเวลามีความซับซ้อนO(n)ในขณะที่คุณแนะนำให้ตรวจสอบสแต็กเพื่อดูว่ามันมีโหนดที่เยี่ยมชมอยู่แล้ว? การสแกนสแต็กจะเพิ่มเวลาในการO(n)รันไทม์เนื่องจากต้องสแกนสแต็กในแต่ละโหนดใหม่ คุณสามารถทำได้O(n)ถ้าคุณทำเครื่องหมายโหนดที่เข้าชม
James Wierzba

ดังที่ Peter กล่าวไว้ซึ่งไม่สมบูรณ์สำหรับกราฟกำกับ ดูคำตอบที่ถูกต้องของ Kurt Peek
ลุคฮัทชิสัน

32

อ้างอิงจาก Lemma 22.11 ของCormen et al., Introduction to Algorithms (CLRS):

กราฟกำกับ G คือ acyclic ถ้าหากการค้นหาความลึกครั้งแรกของ G ไม่ทำให้เกิดขอบหลัง

สิ่งนี้ถูกกล่าวถึงในหลายคำตอบ ที่นี่ฉันจะให้ตัวอย่างรหัสตามบทที่ 22 ของ CLRS ตัวอย่างกราฟแสดงไว้ด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

รหัสหลอกของ CLRS สำหรับการอ่านเชิงลึกครั้งแรก:

ป้อนคำอธิบายรูปภาพที่นี่

ในตัวอย่างในรูปที่ 22.4 CLRS กราฟประกอบด้วยสองต้นไม้ DFS: หนึ่งประกอบด้วยโหนดU , V , XและY , และอื่น ๆ ของโหนดWและZ แต่ละต้นประกอบด้วยหนึ่งขอบหลัง: หนึ่งจากxถึงvและอีกต้นจากzถึงz (self-loop)

การสำนึกหลักคือการที่ขอบด้านหลังจะเกิดขึ้นเมื่อในDFS-VISITฟังก์ชั่นในขณะที่วนรอบเพื่อนบ้านvของuโหนดพบกับGRAYสี

รหัส Python ต่อไปนี้เป็นการดัดแปลง pseudocode ของ CLRS พร้อมกับifclause ที่เพิ่มซึ่งตรวจพบรอบ:

import collections


class Graph(object):
    def __init__(self, edges):
        self.edges = edges
        self.adj = Graph._build_adjacency_list(edges)

    @staticmethod
    def _build_adjacency_list(edges):
        adj = collections.defaultdict(list)
        for edge in edges:
            adj[edge[0]].append(edge[1])
        return adj


def dfs(G):
    discovered = set()
    finished = set()

    for u in G.adj:
        if u not in discovered and u not in finished:
            discovered, finished = dfs_visit(G, u, discovered, finished)


def dfs_visit(G, u, discovered, finished):
    discovered.add(u)

    for v in G.adj[u]:
        # Detect cycles
        if v in discovered:
            print(f"Cycle detected: found a back edge from {u} to {v}.")

        # Recurse into DFS tree
        if v not in finished:
            dfs_visit(G, v, discovered, finished)

    discovered.remove(u)
    finished.add(u)

    return discovered, finished


if __name__ == "__main__":
    G = Graph([
        ('u', 'v'),
        ('u', 'x'),
        ('v', 'y'),
        ('w', 'y'),
        ('w', 'z'),
        ('x', 'v'),
        ('y', 'x'),
        ('z', 'z')])

    dfs(G)

โปรดทราบว่าในตัวอย่างนี้timepseudocode ใน CLRS ไม่ได้ถูกดักจับเพราะเราสนใจตรวจจับวงจรเท่านั้น นอกจากนี้ยังมีรหัสสำเร็จรูปสำหรับการสร้างการแสดงรายการ adjacency ของกราฟจากรายการของขอบ

เมื่อสคริปต์นี้ทำงานสคริปต์จะพิมพ์ผลลัพธ์ต่อไปนี้:

Cycle detected: found a back edge from x to v.
Cycle detected: found a back edge from z to z.

นี่คือขอบด้านหลังในตัวอย่างใน CLRS รูปที่ 22.4


29

เริ่มต้นด้วยการ DFS: วงจรที่มีอยู่และถ้าหากกลับขอบถูกค้นพบในช่วง DFS สิ่งนี้พิสูจน์ได้ว่าเป็นผลมาจากทฤษฎีเส้นทางสีขาว


3
ใช่ผมคิดว่าเหมือนกัน แต่ตอนนี้ไม่ได้พอผมโพสต์วิธี cs.stackexchange.com/questions/7216/find-the-simple-cycles-in-a-directed-graph ของฉัน
jonaprieto

จริง Ajay Garg เพียงบอกเกี่ยวกับวิธีการค้นหา "รอบ" ซึ่งเป็นคำตอบส่วนหนึ่งสำหรับคำถามนี้ ลิงก์ของคุณพูดถึงการค้นหารอบทั้งหมดตามคำถามที่ถาม แต่ดูเหมือนว่ามันใช้วิธีเดียวกันกับ Ajay Garg แต่ก็ทำทรีดีเอฟเอทั้งหมด
Manohar Reddy Poreddy

สิ่งนี้ไม่สมบูรณ์สำหรับกราฟกำกับ ดูคำตอบที่ถูกต้องของ Kurt Peek
ลุคฮัทชิสัน

26

ในความคิดของฉันอัลกอริทึมที่เข้าใจได้มากที่สุดสำหรับการตรวจสอบวงจรในกราฟกำกับคือกราฟสี - อัลกอริทึม

โดยทั่วไปอัลกอริทึมการระบายสีกราฟจะเดินกราฟในลักษณะ DFS (ค้นหาความลึกครั้งแรกซึ่งหมายความว่ามันสำรวจเส้นทางอย่างสมบูรณ์ก่อนที่จะสำรวจเส้นทางอื่น) เมื่อพบว่าขอบด้านหลังจะทำเครื่องหมายกราฟว่ามีลูป

สำหรับคำอธิบายเชิงลึกของอัลกอริทึมการระบายสีกราฟโปรดอ่านบทความนี้: http://www.geeksforgeeks.org/detect-cycle-direct-graph-using-colors/

นอกจากนี้ฉันยังให้การใช้งานการทำสีกราฟใน JavaScript https://github.com/dexcodeinc/graph_algorithm.js/blob/master/graph_algorithm.js


8

หากคุณไม่สามารถเพิ่มคุณสมบัติ "เยี่ยมชม" ให้กับโหนดให้ใช้ชุด (หรือแผนที่) และเพียงเพิ่มโหนดที่เยี่ยมชมทั้งหมดไปยังชุดยกเว้นว่ามันอยู่ในชุดแล้ว ใช้คีย์ที่ไม่ซ้ำกันหรือที่อยู่ของวัตถุเป็น "กุญแจ"

นอกจากนี้ยังให้ข้อมูลเกี่ยวกับโหนด "รูท" ของการพึ่งพาแบบวนรอบซึ่งจะมีประโยชน์เมื่อผู้ใช้ต้องแก้ไขปัญหา

วิธีแก้ไขปัญหาอื่นคือลองค้นหาการพึ่งพาถัดไปเพื่อเรียกใช้งาน สำหรับสิ่งนี้คุณต้องมีสแต็คบางส่วนที่คุณสามารถจำได้ว่าคุณอยู่ที่ไหนตอนนี้และสิ่งที่คุณต้องทำต่อไป ตรวจสอบว่าการอ้างอิงมีอยู่ในสแต็กนี้ก่อนที่คุณจะดำเนินการ ถ้าเป็นเช่นนั้นคุณจะพบวงจร

ในขณะนี้อาจดูเหมือนว่ามีความซับซ้อนของ O (N * M) คุณต้องจำไว้ว่าสแต็คมีความลึกที่ จำกัด มาก (ดังนั้น N จึงมีขนาดเล็ก) และ M นั้นเล็กลงด้วยการพึ่งพาแต่ละครั้งที่คุณสามารถทำเครื่องหมายเป็น "ดำเนินการ" บวก คุณสามารถหยุดการค้นหาเมื่อคุณพบใบไม้ (ดังนั้นคุณไม่จำเป็นต้องตรวจสอบทุกโหนด -> M จะเล็กเกินไป)

ใน MetaMake ฉันสร้างกราฟเป็นรายการและลบทุกโหนดเมื่อฉันประมวลผลซึ่งลดปริมาณการค้นหาโดยธรรมชาติ ฉันไม่เคยต้องเรียกใช้การตรวจสอบที่เป็นอิสระทุกอย่างเกิดขึ้นโดยอัตโนมัติในระหว่างการดำเนินการตามปกติ

หากคุณต้องการโหมด "ทดสอบเท่านั้น" เพียงเพิ่มแฟล็ก "dry-run" ซึ่งปิดใช้งานการเรียกใช้งานจริง


7

ไม่มีอัลกอริทึมที่สามารถค้นหารอบทั้งหมดในกราฟกำกับในเวลาพหุนาม สมมติว่ากราฟกำกับมีโหนดและโหนดทุกคู่มีการเชื่อมต่อซึ่งกันและกันซึ่งหมายความว่าคุณมีกราฟที่สมบูรณ์ ดังนั้นเซตย่อยที่ไม่ว่างเปล่าของโหนดเหล่านี้บ่งบอกถึงวัฏจักรและมีจำนวน 2 ^ n-1 ของเซตย่อยดังกล่าว ดังนั้นจึงไม่มีอัลกอริธึมเวลาพหุนาม ดังนั้นสมมติว่าคุณมีอัลกอริทึมที่มีประสิทธิภาพ (ไม่โง่) ซึ่งสามารถบอกจำนวนรอบการชี้นำในกราฟได้คุณสามารถค้นหาส่วนประกอบที่เชื่อมต่อที่แข็งแกร่งก่อนจากนั้นใช้อัลกอริทึมของคุณกับส่วนประกอบที่เชื่อมต่อเหล่านี้ เนื่องจากวงจรมีอยู่เฉพาะภายในส่วนประกอบเท่านั้น


1
เป็นจริงถ้าจำนวนโหนดถูกใช้เป็นขนาดของอินพุต คุณสามารถอธิบายความซับซ้อนรันไทม์ในแง่ของจำนวนของขอบหรือรอบหรือการรวมกันของมาตรการเหล่านี้ อัลกอริทึม "การค้นหาวงจรเบื้องต้นทั้งหมดของกราฟกำกับ" โดย Donald B. Johnson มีเวลาทำงานพหุนามที่กำหนดโดย O ((n + e) ​​(c + 1)) โดยที่ n คือจำนวนโหนดและจำนวนขอบ และ c จำนวนวงจรพื้นฐานของกราฟ และนี่คือการใช้ Java ของฉันของขั้นตอนวิธีนี้: github.com/1123/johnson
user152468

4

ฉันใช้ปัญหานี้ใน sml (การเขียนโปรแกรมที่จำเป็น) นี่คือโครงร่าง ค้นหาโหนดทั้งหมดที่มี indegree หรือ outdegree เป็น 0 โหนดดังกล่าวไม่สามารถเป็นส่วนหนึ่งของวงจรได้ (โปรดลบออก) จากนั้นลบขอบขาเข้าหรือขาออกทั้งหมดออกจากโหนดดังกล่าว ใช้กระบวนการนี้ซ้ำ ๆ กับกราฟผลลัพธ์ หากในตอนท้ายคุณไม่ได้อยู่กับโหนดหรือขอบกราฟจะไม่มีวัฏจักรใด ๆ


2

วิธีที่ฉันทำคือจัดเรียงโทโพโลยีนับจำนวนจุดยอดเยี่ยม หากตัวเลขนั้นน้อยกว่าจำนวนยอดรวมทั้งหมดใน DAG คุณมีรอบ


4
ที่ไม่สมเหตุสมผล หากกราฟมีวัฏจักรแสดงว่าไม่มีการเรียงโทโพโลยีซึ่งหมายความว่าอัลกอริธึมที่ถูกต้องสำหรับการเรียงโทโพโลยีจะถูกยกเลิก
sleske

4
จากวิกิพีเดีย: อัลกอริธึมการเรียงลำดับโทโพโลยีจำนวนมากจะตรวจพบวัฏจักรเช่นกัน
Oleg Mikheev

1
@OlegMikheev ใช่ แต่ Steve กำลังพูดว่า "ถ้าตัวเลขนั้นน้อยกว่าจำนวนยอดรวมทั้งหมดใน DAG คุณมีรอบ" ซึ่งไม่สมเหตุสมผล
nbro

@nbro ฉันเดิมพันพวกเขาหมายถึงตัวแปรของอัลกอริธึมการเรียงลำดับทอพอโลยีซึ่งยกเลิกเมื่อไม่มีการเรียงโทโพโลยีอยู่ (และจากนั้นพวกเขาไม่เยี่ยมชมจุดยอดทั้งหมด)
maaartinus

หากคุณทำการเรียงโทโพโลยีบนกราฟที่มีวงรอบคุณจะได้คำสั่งที่มีขอบที่ไม่ดีจำนวนน้อยที่สุด (หมายเลขคำสั่งซื้อ> หมายเลขคำสั่งของเพื่อนบ้าน) แต่หลังจากที่คุณต้องจัดเรียงมันง่ายต่อการตรวจจับขอบที่ไม่ดีเหล่านั้นส่งผลให้การตรวจสอบกราฟที่มีรอบ
UGP

2

/mathpro/16393/finding-a-cycle-of-fixed-lengthฉันชอบโซลูชันนี้ดีที่สุดโดยเฉพาะสำหรับความยาว 4 :)

ตัวช่วยสร้าง phys ยังบอกด้วยว่าคุณต้องทำ O (V ^ 2) ฉันเชื่อว่าเราต้องการเพียง O (V) / O (V + E) หากกราฟเชื่อมต่อแล้ว DFS จะไปที่โหนดทั้งหมด หากกราฟมีการเชื่อมต่อกราฟย่อยแล้วแต่ละครั้งที่เราเรียกใช้ DFS บนจุดยอดของกราฟย่อยนี้เราจะพบจุดยอดที่เชื่อมต่อและไม่ต้องพิจารณาสิ่งเหล่านี้สำหรับการเรียกใช้ DFS ครั้งถัดไป ดังนั้นความเป็นไปได้ในการทำงานสำหรับแต่ละจุดสุดยอดจึงไม่ถูกต้อง


1

หาก DFS พบขอบที่ชี้ไปยังจุดสุดยอดที่เยี่ยมชมแล้วคุณจะมีวัฏจักรอยู่ที่นั่น


1
ล้มเหลวใน 1,2,3: 1,2; 1,3; 2,3;
แมวที่มีเสียงดัง

4
@ JakeGreene ดูที่นี่: i.imgur.com/tEkM5xy.png เรียบง่ายพอที่จะเข้าใจ ให้บอกว่าคุณเริ่มต้นจาก 0 จากนั้นคุณไปที่โหนด 1 ไม่มีเส้นทางอีกต่อไปแล้ว reucrsion กลับไป ตอนนี้คุณไปที่โหนด 2 ซึ่งมีขอบถึงจุดสุดยอด 1 ซึ่งเคยไปแล้ว ในความคิดของคุณคุณจะมีรอบแล้ว - และคุณไม่มีหนึ่งจริงๆ
แมวที่มีเสียงดัง

3
@kittyPL กราฟนั้นไม่มีวัฏจักร จากวิกิพีเดีย: "วงจรชี้นำในกราฟกำกับคือลำดับของจุดยอดเริ่มต้นและสิ้นสุดที่จุดยอดเดียวกันเช่นนั้นสำหรับจุดยอดต่อเนื่องของวงจรสองจุดต่อเนื่องกันจะมีขอบกำกับจากจุดสุดยอดก่อนหน้าไปยังจุดถัดไป" จะต้องสามารถปฏิบัติตามเส้นทางจาก V ที่นำกลับไปสู่ ​​V สำหรับวงจรกำกับ วิธีการแก้ปัญหาของ mafonya ใช้ได้กับปัญหาที่ได้รับ
Jake Greene

2
@ JakeGreene แน่นอนมันไม่ได้ การใช้อัลกอริทึมของคุณและเริ่มจาก 1 คุณจะต้องตรวจสอบวัฏจักรต่อไป ... อัลกอริทึมนี้แย่มาก ... โดยปกติแล้วมันจะเพียงพอที่จะเดินถอยหลังเมื่อใดก็ตามที่คุณพบจุดสุดยอดที่เยี่ยมชม
แมวที่มีเสียงดัง

6
@kittyPL DFS ทำงานเพื่อตรวจสอบรอบจากโหนดเริ่มต้นที่กำหนด แต่เมื่อทำ DFS คุณจะต้องใช้สีที่ไปที่โหนดเพื่อแยกความแตกต่างของ cross-edge ครั้งแรกที่เข้าสู่จุดสุดยอดมันจะกลายเป็นสีเทาจากนั้นคุณเปลี่ยนเป็นสีดำเมื่อขอบทั้งหมดถูกเยี่ยม ถ้าเมื่อทำ DFS คุณจะตีจุดสุดยอดสีเทาดังนั้นจุดยอดนั้นจะเป็นบรรพบุรุษ (เช่น: คุณมีรอบ) ถ้าจุดสุดยอดเป็นสีดำแสดงว่าเป็นเพียงการไขว้กัน
Kyrra

0

ดังที่คุณกล่าวว่าคุณมีงานที่ต้องดำเนินการในลำดับที่แน่นอน Topological sortให้คุณต้องสั่งซื้อสำหรับการจัดตารางเวลาของงาน (หรือสำหรับปัญหาการพึ่งพาถ้ามันเป็นdirect acyclic graph) รันdfsและดูแลรักษารายการและเริ่มเพิ่มโหนดในตอนต้นของรายการและหากคุณพบโหนดที่มีการเยี่ยมชมแล้ว จากนั้นคุณจะพบวงจรในกราฟที่กำหนด


-11

ถ้ากราฟตรงตามคุณสมบัตินี้

|e| > |v| - 1

ดังนั้นกราฟจะมีรอบอย่างน้อยที่สุด


10
นั่นอาจเป็นจริงสำหรับกราฟที่ไม่ได้บอกทิศทาง แต่ก็ไม่แน่นอนสำหรับกราฟกำกับ
Hans-Peter Störr

6
ตัวอย่างตัวนับจะเป็น A-> B, B-> C, A-> C
user152468

จุดยอดไม่ทั้งหมดมีขอบ
Debanjan Dhar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.