ครั้งแรกพื้นหลังเล็กน้อยเพื่อระบุว่าทำไมจึงไม่ใช่ปัญหายาก การไหลผ่านแม่น้ำรับรองว่าส่วนของมันหากถูกต้องดิจิทัลสามารถมุ่งเน้นในการสร้างกราฟ acyclic (DAG) ในทางกลับกันกราฟสามารถสั่งซื้อได้เป็นเส้นตรงและถ้าหากมันเป็น DAG โดยใช้เทคนิคที่เรียกว่าการจัดเรียงทอพอโลยี การจัดเรียงโทโพโลยีนั้นรวดเร็ว: ความต้องการด้านเวลาและพื้นที่ของมันคือทั้ง O (| E | + | V |) (E = จำนวนขอบ, V = จำนวนจุดยอด) ซึ่งดีเท่าที่จะได้รับ การสร้างการเรียงลำดับแบบเชิงเส้นจะช่วยให้ค้นหาเตียงหลักได้ง่าย
ที่นี่จึงเป็นร่างของอัลกอริทึม ปากลำธารนอนอยู่บนเตียงหลัก ย้ายอัปสตรีมไปตามแต่ละสาขาที่ติดกับปาก (อาจมีมากกว่าหนึ่งหากปากเป็นจุดบรรจบกัน) และพบเตียงใหญ่ซ้ำ ๆ ที่ทอดลงไปสู่กิ่งนั้น เลือกสาขาที่มีความยาวรวมมากที่สุดนั่นคือ "ลิงก์ย้อนกลับ" ของคุณตามเตียงหลัก
จะทำให้เรื่องนี้ชัดเจนฉันมีบางส่วน (ทดสอบ) pseudocode อินพุตเป็นชุดของส่วนของเส้น (หรือส่วนโค้ง) S (ประกอบด้วยสตรีมแบบดิจิทัล) แต่ละอันมีจุดเริ่มต้นที่แตกต่างกันสองจุด (S) และจุดสิ้นสุด (S) และความยาวบวกความยาว (S); และปากแม่น้ำพีซึ่งเป็นจุดที่ เอาท์พุทเป็นลำดับของส่วนรวมกันปากที่มีจุดต้นน้ำที่ห่างไกลที่สุด
เราจะต้องทำงานกับ "กลุ่มที่ทำเครื่องหมายไว้" (S, p) เหล่านี้ประกอบด้วยหนึ่งในกลุ่มSพร้อมกับหนึ่งในสองปลายทางของมัน, p . เราจะต้องค้นหาเซกเมนต์ทั้งหมดSที่ใช้จุดปลายร่วมกับโพรบจุดqทำเครื่องหมายเซกเมนต์เหล่านั้นด้วยจุดสิ้นสุดอื่น ๆและส่งคืนชุด:
Procedure Extract(q: point, A: set of segments): Set of marked segments.
เมื่อไม่พบเซ็กเมนต์ดังกล่าว Extract จะต้องส่งคืนชุดว่าง เป็นผลข้างเคียง,สารสกัดจากต้องเอาทุกกลุ่มก็จะกลับมาจากชุดA,จึงปรับเปลี่ยนตัวเอง
ฉันไม่ให้การดำเนินการของสารสกัดจาก: GIS ของคุณจะให้ความสามารถในการเลือกกลุ่มSร่วมกันปลายทางกับคิว การทำเครื่องหมายพวกเขาเป็นเพียงเรื่องของการเปรียบเทียบทั้งจุดเริ่มต้น (S) และจุดสิ้นสุด (S) กับqและกลับจุดใดจุดหนึ่งในสองจุดไม่ตรงกัน
ตอนนี้เราพร้อมที่จะแก้ปัญหาแล้ว
Procedure LongestUpstreamReach(p: point, A: set of segments): (Array of segments, length)
A0 = A // Optional: preserves A
C = Extract(p, A0) // Removes found segments from the set A0!
L = 0; B = empty array
For each (S,q) in C: // Loop over the segments meeting point p
(B0, M) = LongestUpstreamReach(q, A0)
If (length(S) + M > L) then
B = append(S, B0)
L = length(S) + M
End if
End for
Return (B, L)
End LongestUpstreamReach
ขั้นตอน "ผนวก (S, B0)" ติดกลุ่มSที่ส่วนท้ายของอาร์เรย์B0และส่งกลับอาร์เรย์ใหม่
(หากกระแสเป็นต้นไม้จริงๆ: ไม่มีเกาะ, ทะเลสาบ, braids ฯลฯ - จากนั้นคุณสามารถแจกจ่ายด้วยขั้นตอนการคัดลอกAไปที่A0 )
คำถามเดิมตอบโดยการรวมกันของเซกเมนต์ที่ส่งคืนโดย LongestUpstreamReach
เพื่อแสดงภาพลองพิจารณาสตรีมในแผนที่ดั้งเดิม สมมติว่ามันเป็นดิจิทัลเป็นชุดของเจ็ดส่วนโค้ง Arc ไปจากปากที่จุด 0 (ด้านบนของแผนที่ที่ถูกต้องในรูปด้านล่างซึ่งเป็นที่หมุน) ต้นน้ำไปบรรจบกันที่จุดแรก 1. มันโค้งยาว 8 หน่วยพูดยาว ส่วนโค้งbแยกไปทางซ้าย (ในแผนที่) และสั้นประมาณ 2 หน่วย ส่วนโค้งcจะอยู่ทางด้านขวาและมีความยาวประมาณ 4 หน่วย ฯลฯ การปล่อย "b", "d" และ "f" หมายถึงกิ่งด้านซ้ายเมื่อเราไปจากบนลงล่างบนแผนที่และ "a" "c", "e", และ "g" สาขาอื่น ๆ , และการนับจำนวนจุดยอด 0 ถึง 7, เราสามารถแสดงกราฟเป็นชุดของส่วนโค้งได้อย่างเป็นนามธรรม
A = {a=(0,1), b=(1,2), c=(1,3), d=(3,4), e=(3,5), f=(5,6), g=(5,7)}
ฉันจะสมมติว่าพวกเขามีความยาว 8, 2, 4, 1, 2, 2, 2 สำหรับaถึงgตามลำดับ จุดยอดปาก 0
ตัวอย่างแรกคือการเรียกไปยัง Extract (5, {f, g}) มันจะส่งคืนชุดของส่วนที่ทำเครื่องหมายไว้ {(f, 6), (g, 7)} โปรดทราบว่าจุดสุดยอด 5 อยู่ที่จุดบรรจบของส่วนโค้งfและg (ส่วนโค้งทั้งสองที่ด้านล่างของแผนที่) และ (f, 6) และ (g, 7) ทำเครื่องหมายส่วนโค้งเหล่านี้แต่ละจุดด้วยจุดปลายน้ำ
ตัวอย่างถัดไปคือการเรียกใช้ LongestUpstreamReach (0, A) การดำเนินการแรกที่ใช้คือการเรียกไปยัง Extract (0, A) ส่งคืนชุดที่มีเซ็กเมนต์ที่ทำเครื่องหมาย (a, 1) และลบเซ็กเมนต์aออกจากชุดA0ซึ่งตอนนี้เท่ากับ {b, c, d, e, f, g} มีการวนซ้ำหนึ่งรอบโดยที่ (S, q) = (a, 1) ในระหว่างการทำซ้ำนี้มีการโทรไปยัง LongestUpstreamReach (1, A0) การเรียกซ้ำนั้นจะต้องส่งคืนทั้งลำดับ (g, e, c) หรือ (f, e, c): ทั้งคู่ใช้ได้อย่างเท่าเทียมกัน ความยาว (M) ที่ส่งคืนคือ 4 + 2 + 2 = 8 (โปรดทราบว่า LongestUpstreamReach ไม่ได้แก้ไขA0 ) ในตอนท้ายของลูปให้แบ่งเซกเมนต์aได้ถูกผนวกเข้ากับสตรีมเบดและความยาวเพิ่มขึ้นเป็น 8 + 8 = 16 ดังนั้นค่าส่งคืนแรกประกอบด้วยลำดับ (g, e, c, a) หรือ (f, e, c, a), ด้วยความยาว 16 ในทั้งสองกรณีสำหรับค่าส่งคืนที่สอง สิ่งนี้แสดงให้เห็นว่า LongestUpstreamReach เพิ่งเคลื่อนทวนกระแสน้ำออกมาจากปากเลือกที่มาบรรจบกันในแต่ละสาขาด้วยระยะทางที่ไกลที่สุดและไปตามเส้นทางของมัน
การใช้งานที่มีประสิทธิภาพมากขึ้นเป็นไปได้เมื่อมี braids และเกาะจำนวนมาก แต่สำหรับจุดประสงค์ส่วนใหญ่จะมีความพยายามเล็กน้อยหาก LongestUpstreamReach ดำเนินการตรงตามที่แสดงเพราะในการบรรจบกันไม่มีการซ้อนทับกันระหว่างการค้นหาในสาขาต่างๆ: การคำนวณ เวลา (และความลึกของสแต็ค) จะเป็นสัดส่วนโดยตรงกับจำนวนรวมของกลุ่ม