ความน่าเชื่อถือของกราฟที่ไม่ได้บอกทิศทางเป็นแนวคิดที่สำคัญมากในทฤษฎีกราฟ อัลกอริธึมกราฟจำนวนมากได้รับการคิดค้นขึ้นมาซึ่งทำงานได้รวดเร็วหากคุณมีการสลายตัวของกราฟที่มีความกังวลเล็กน้อย
treewidth มักจะถูกกำหนดในแง่ของการย่อยสลายต้นไม้ นี่คือกราฟและแผนภูมิย่อยสลายของกราฟความเอื้อเฟื้อจาก Wikipedia:
การสลายตัวของต้นไม้เป็นต้นไม้ที่จุดยอดแต่ละจุดเชื่อมโยงกับเซตย่อยของจุดยอดของกราฟต้นฉบับด้วยคุณสมบัติดังต่อไปนี้:
- จุดยอดทุกอันในกราฟต้นฉบับจะอยู่ในเซตย่อยอย่างน้อยหนึ่งค่า
- ขอบทุกเส้นในกราฟดั้งเดิมมีจุดยอดทั้งคู่ในเซตย่อยอย่างน้อยหนึ่งค่า
- จุดยอดทั้งหมดในการสลายตัวที่มีส่วนย่อยประกอบด้วยจุดสุดยอดเดิมที่กำหนดมีการเชื่อมต่อ
คุณสามารถตรวจสอบว่าการสลายตัวข้างต้นเป็นไปตามกฎเหล่านี้ ความกว้างของการย่อยสลายต้นไม้คือขนาดของเซตย่อยที่ใหญ่ที่สุดลบหนึ่ง ดังนั้นจึงเป็นเรื่องที่สองสำหรับการสลายตัวข้างต้น ความกว้างของกราฟคือความกว้างที่เล็กที่สุดของการย่อยสลายต้นไม้ของกราฟนั้น
ในความท้าทายนี้คุณจะได้รับกราฟที่เชื่อมต่อและไม่มีทิศทางและคุณจะต้องพบความกังวล
ในขณะที่การค้นหาการย่อยสลายต้นไม้เป็นเรื่องยากมีวิธีอื่นในการคำนวณ treewidth หน้าวิกิพีเดียมีข้อมูลเพิ่มเติม แต่วิธีหนึ่งในการคำนวณ treewidth ที่ไม่ได้กล่าวถึงซึ่งมักใช้ในอัลกอริทึมในการคำนวณ treewidth นั้นคือความกว้างขั้นต่ำในการกำจัด ดูที่นี่สำหรับกระดาษโดยใช้ข้อเท็จจริงนี้
ในการกำจัดการเรียงลำดับหนึ่งจะกำจัดจุดยอดทั้งหมดของกราฟทีละครั้ง เมื่อกำจัดจุดสุดยอดแต่ละจุดขอบจะถูกเพิ่มเข้ามาเชื่อมต่อกับเพื่อนบ้านของจุดสุดยอดทั้งหมดซึ่งกันและกัน สิ่งนี้ซ้ำจนกระทั่งจุดยอดทั้งหมดหายไป ความกว้างของการสั่งตัดเป็นจำนวนเพื่อนบ้านมากที่สุดที่จุดสุดยอดใด ๆ ที่ถูกกำจัดมีในระหว่างกระบวนการนี้ treewidth เท่ากับขั้นต่ำสำหรับการเรียงลำดับความกว้างของการคัดออกทั้งหมด นี่คือตัวอย่างโปรแกรมที่ใช้ข้อเท็จจริงนี้เพื่อคำนวณความน่าเชื่อถือ:
import itertools
def elimination_width(graph):
max_neighbors = 0
for i in sorted(set(itertools.chain.from_iterable(graph))):
neighbors = set([a for (a, b) in graph if b == i] + [b for (a, b) in graph if a == i])
max_neighbors = max(len(neighbors), max_neighbors)
graph = [edge for edge in graph if i not in edge] + [(a, b) for a in neighbors for b in neighbors if a < b]
return max_neighbors
def treewidth(graph):
vertices = list(set(itertools.chain.from_iterable(graph)))
min_width = len(vertices)
for permutation in itertools.permutations(vertices):
new_graph = [(permutation[vertices.index(a)], permutation[vertices.index(b)]) for (a, b) in graph]
min_width = min(elimination_width(new_graph), min_width)
return min_width
if __name__ == '__main__':
graph = [('a', 'b'), ('a', 'c'), ('b', 'c'), ('b', 'e'), ('b', 'f'), ('b', 'g'),
('c', 'd'), ('c', 'e'), ('d', 'e'), ('e', 'g'), ('e', 'h'), ('f', 'g'), ('g', 'h')]
print(treewidth(graph))
ตัวอย่าง:
[(0, 1), (0, 2), (0, 3), (2, 4), (3, 5)]
1
[(0, 1), (0, 2), (1, 2), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (3, 4), (4, 6), (4, 7), (5, 6), (6, 7)]
2
[(0, 1), (0, 3), (1, 2), (1, 4), (2, 5), (3, 4), (3, 6), (4, 5), (4, 7), (5, 8), (6, 7), (7, 8)]
3
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
4
คุณจะได้รับกราฟเป็นอินพุตและคุณต้องส่งคืน treewidth เป็นเอาต์พุต รูปแบบอินพุตมีความยืดหยุ่น คุณอาจใช้รายการของขอบแผนที่ adjacency หรือเมทริกซ์ adjacency เป็นอินพุต หากคุณต้องการใช้รูปแบบการป้อนข้อมูลอื่นให้ถามในความคิดเห็น คุณอาจสมมติว่าอินพุตนั้นเชื่อมต่อกันและคุณอาจสร้างสมมติฐานนั้นในรูปแบบอินพุตของคุณเช่นโดยใช้รายการขอบ
แก้ไข: การดำเนินการในตัวซึ่งคำนวณความน่าเชื่อถือไม่ได้รับอนุญาต ฉันขอโทษที่ไม่ได้ระบุสิ่งนี้ไว้ล่วงหน้า
รหัสที่สั้นที่สุดชนะ
(V,E)
นี่จะเป็นอินพุตที่ถูกต้องหรือไม่