เราจะใช้อัลกอริธึมกราฟที่ต้องการการย่อและขยายส่วนประกอบที่เชื่อมต่ออย่างมีประสิทธิภาพได้อย่างไร

มีอัลกอริทึมบางอย่าง เช่น Edmond's Algorithm หรือ Boruvka's Algorithm ซึ่งต้องการให้โปรแกรมเมอร์สร้างกราฟซึ่งได้มาจากการหดตัวของบางโหนดให้เป็นโหนดเดียว และ ต่อมาก็ขยายกลับ

คำอธิบายอย่างเป็นทางการของการหดตัวมีดังนี้:

ให้ G เป็นกราฟที่มีจุดยอด V และขอบ E ให้ C เป็นส่วนประกอบที่เชื่อมต่อกันของ G การย่อของ G เทียบกับ C ถูกกำหนดให้เป็นกราฟบน V - nodes(C) + C* โดยที่ C* คือ "supernode" ที่แสดงถึงองค์ประกอบที่ทำสัญญา ขอบที่ไม่เกี่ยวข้องกับจุดยอดใน C เป็นไปตามที่เป็นอยู่ ขอบที่มีจุดสิ้นสุดใน C เชื่อมต่อกับ C* แล้ว

ตัวอย่างเช่น ขั้นตอนกลางในอัลกอริทึมของ Edmond อาจต้องมีการหดตัวของวงจร การดำเนินการบนกราฟที่หดตัว จากนั้นจึงขยายกลับอีกครั้ง

ฉันไม่ชัดเจนสำหรับฉันว่าจะใช้อัลกอริทึมดั้งเดิมดังกล่าวได้อย่างไรโดยใช้การเป็นตัวแทนเช่นรายการคำคุณศัพท์

อะไรจะเป็นวิธีที่สวยงามและมีประสิทธิภาพในการแสดงกราฟเพื่อให้สามารถย่อขนาดในขณะที่จดจำข้อมูลที่เกี่ยวข้องเพื่อขยายกราฟได้


person Agnishom Chattopadhyay    schedule 01.04.2018    source แหล่งที่มา
comment
โหนดที่ทำสัญญาสามารถเป็นส่วนหนึ่งของโหนดที่ทำสัญญาที่ใหญ่กว่าได้หรือไม่? นั่นคือ supernodes สามารถซ้อนกันได้หรือไม่?   -  person Eric Lippert    schedule 01.04.2018
comment
@EricLippert ใช่ โครงสร้างดังกล่าวอาจจำเป็นในการนำอัลกอริทึมของ Edmond ไปใช้ ซึ่งอาจมีการเรียกซ้ำหลายครั้ง   -  person Agnishom Chattopadhyay    schedule 01.04.2018
comment
โดยปกติแล้วจะมีวิธีที่ง่ายมากซึ่งขึ้นอยู่กับรายละเอียดอื่นๆ ของการนำไปปฏิบัติ กล่าวคือ วิธีที่ดีที่สุดมักจะไม่ใช่แนวทางทั่วไปที่นำไปใช้กับอัลกอริธึมส่วนใหญ่หรือการใช้งานส่วนใหญ่ของอัลกอริธึมส่วนใหญ่   -  person Matt Timmermans    schedule 01.04.2018
comment
ในกรณีทั่วไป สิ่งที่ใกล้เคียงที่สุดที่อยู่ในใจคือโครงสร้างข้อมูลสำหรับการสืบค้นการเชื่อมต่อในกราฟแบบไดนามิก (en.wikipedia.org/wiki/Dynamic_connectivity#General_graphs_2) วิกิพีเดียกล่าวว่าการสืบค้นการเชื่อมต่อแบบไดนามิก (ด้วยการลบขอบและการแทรกในกราฟแบบไม่มีทิศทาง) สามารถรองรับได้ในเวลาโพลีล็อกต่อการดำเนินการ   -  person Neal Young    schedule 01.04.2018


คำตอบ (2)


ฉันจะใช้โครงสร้างข้อมูล disjoint-set หรือที่เรียกว่า ยูเนี่ยน–ค้นหา โครงสร้างข้อมูล ลองนึกภาพแต่ละจุดยอดเป็นเซตตั้งแต่แรก ตอนนี้การทำงานดำเนินไปดังนี้:

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

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

person Sumeet    schedule 01.04.2018
comment
ในโครงสร้างข้อมูล union-find ที่ฉันรู้จัก Union ไม่สามารถกลับด้านได้อย่างง่ายดาย การดำเนินการค้นหาจะปรับเปลี่ยนโครงสร้างข้อมูล (เช่น ตามเส้นทางที่ติดตามเพื่อค้นหา การค้นหาจะเปลี่ยนแต่ละพอยน์เตอร์ให้ชี้ไปที่รูทปัจจุบัน) สิ่งนี้จำเป็นสำหรับประสิทธิภาพ เนื่องจากการดำเนินการ Find ปรับเปลี่ยนโครงสร้างข้อมูลและสูญเสียข้อมูล คุณมีวิธีการขยายอย่างมีประสิทธิภาพอย่างไร - person Neal Young; 01.04.2018
comment
@NealYoung สิ่งที่คุณกำลังพูดถึงคือการวิเคราะห์พฤติกรรมการบีบอัดเส้นทาง? อย่างไรก็ตาม ในทางกลับกัน ฉันแค่ชี้ไปในทิศทางของโครงสร้างข้อมูลที่เป็นไปได้ที่สามารถนำมาใช้ได้ แต่แม้แต่วรรณกรรมก็ไม่ได้พูดถึงการผกผัน ดังนั้น ฉันจึงปล่อยให้มันเป็นหน้าที่ของ OP สำหรับรายละเอียดการนำไปปฏิบัติ - person Sumeet; 01.04.2018
comment
ใช่ การบีบอัดเส้นทาง ตามที่กำหนดโดยโครงสร้างข้อมูลที่อธิบายไว้ในลิงก์วิกิพีเดียของคุณ มีใครรู้รายละเอียดการใช้งานที่คุณทิ้งไว้ให้กับ OP หรือไม่ ไม่ไกลเท่าที่ฉันรู้ - person Neal Young; 01.04.2018
comment
@NealYoung เมื่อคุณทำงานกับฉากต่างๆ จริง ๆ คุณจะทำงานกับ find บ่อยพอที่จะเข้าถึงการปรับให้เหมาะสม แต่ที่นี่คุณจะหดตัวหรือขยาย อย่างที่ฉันบอกไปว่าฉันได้ชี้ไปในทิศทางที่ป้อนข้อมูลเท่านั้น - person Sumeet; 01.04.2018

ก่อนอื่น ฉันชอบแนวคิดของคำตอบของสุมีต ซิงห์ และคุณอาจสำรวจเรื่องนี้ก่อน ฉันมีความคิดที่คล้ายกันแต่รายละเอียดแตกต่างกันเล็กน้อย

น่าเสียดายที่ตอนนี้ฉันไม่ได้อยู่ในจุดที่ฉันสามารถวาดไดอะแกรมได้ ซึ่งจะช่วยได้มากในตอนนี้ ผมขอลองอธิบายสิ่งที่ผมมีในใจให้ชัดเจน

โซลูชันเกี่ยวข้องกับการสร้างโหนดใหม่สองประเภท:

  • "supernode" แสดงถึงชุดที่ทำสัญญา
  • "โหนดการส่งต่อ" เป็นพร็อกซีสำหรับซูเปอร์โหนดที่รู้วิธี "เลิกทำ" การสร้างมัน
  • โหนดการส่งต่อมีการอ้างอิงสามรายการ: ไปยังโหนดซุปเปอร์โหนด ไปยังโหนด "ภายนอก" และไปยังโหนด "ภายใน"
  • ซูเปอร์โหนดมีรายการโหนดการส่งต่อทั้งหมด

การหดตัว:

พิจารณาส่วนประกอบที่เชื่อมต่อของคุณ G

  • สร้าง "supernode" ที่แสดงถึงส่วนประกอบที่เชื่อมต่อนี้

  • สำหรับแต่ละโหนดใน G อาจมีขอบที่เชื่อมต่อกับโหนด ไม่ใช่ ใน G เรียกขอบเหล่านั้นว่า e1, e2, e3, ...

  • สร้างโหนดการส่งต่อ F1, F2, F3... สำหรับแต่ละขอบเหล่านั้น

  • ตอนนี้สำหรับแต่ละขอบเหล่านั้น สมมติว่า e1 มาจาก A1 (ไม่ใช่ใน G) ถึง B1 (ใน G) ลบขอบ A1-B1 ออกจากกราฟ เพิ่มขอบ A1-F1 A1 กลายเป็นโหนดภายนอกของ F1 และ B1 กลายเป็นโหนดภายในของ F1

การขยายตัวเป็นเพียงสิ่งที่ตรงกันข้าม:

  • สำหรับแต่ละโหนดการส่งต่อ F ใน supernode ให้ลบขอบออกจากโหนดภายนอก เพิ่มขอบจากโหนดภายนอกไปยังโหนดภายในด้านหลัง และลบโหนดการส่งต่อทั้งหมด

  • ลบซุปเปอร์โหนด


บิตที่ยุ่งยากจะมาในการดำเนินการกราฟ หากคุณถามว่า "เพื่อนบ้านของคุณคืออะไร" ของโหนดการส่งต่อ จะต้องส่งต่อคำขอนั้นไปยัง supernode และ supernode จะต้องพูดว่า "โหนดภายนอกทั้งหมดของโหนดการส่งต่อทั้งหมดของฉัน" และอื่นๆ

person Eric Lippert    schedule 01.04.2018
comment
ฉันสงสัยว่ามันจะง่ายกว่าไหมที่จะมีโหนดการส่งต่ออยู่ภายในซุปเปอร์โหนดแทนที่จะนั่งล้อมรอบมัน ด้วยวิธีนี้โหนดอื่นๆ ทั้งหมดจะเห็นว่าตนเองเชื่อมต่อกับ supernode และคุณจะไม่มีปัญหาในการส่งต่อการดำเนินการอีกต่อไป คุณยังคงต้องใช้โหนดการส่งต่อเพื่อเชื่อมต่อโหนดภายในกับขอบภายนอก แต่โหนดเหล่านั้นจะต้องเข้ามามีบทบาทหากคุณกำลังขยาย supernode หรือเปลี่ยนจากภายในไปเป็นภายนอก (หรือย้อนกลับ) - person Wearwolf; 03.04.2018
comment
@Wearwolf: แน่นอนว่ามีหลายวิธีในการแก้ปัญหานี้ แต่จุดสำคัญคือ: (1) บางแห่งมีโครงสร้างข้อมูลที่รู้ว่าลิงก์เคยเป็นอะไรและสามารถกู้คืนได้ และ (2) สิ่งใดก็ตามที่ดูเหมือนจุดยอดจากมุมมองของขอบที่เข้ามา - person Eric Lippert; 03.04.2018