Pertama, sedikit latar belakang untuk menunjukkan mengapa ini bukan masalah yang sulit. Aliran melalui sungai menjamin bahwa segmennya, jika terdigitasi dengan benar, selalu dapat berorientasi untuk membentuk grafik asiklik terarah (DAG). Pada gilirannya, grafik dapat dipesan secara linier jika dan hanya jika itu adalah DAG, menggunakan teknik yang dikenal sebagai semacam topologi . Penyortiran topologis cepat: persyaratan waktu dan ruang keduanya O (| E | + | V |) (E = jumlah tepi, V = jumlah simpul), yang sama baiknya dengan yang didapat. Membuat urutan linier seperti itu akan membuatnya mudah untuk menemukan aliran utama.
Di sini, kemudian, adalah sketsa dari suatu algoritma . Mulut sungai itu terletak di sepanjang tempat tidur utamanya. Bergerak hulu sepanjang setiap cabang yang melekat pada mulut (mungkin ada lebih dari satu, jika mulut adalah pertemuan) dan secara rekursif menemukan tempat tidur utama mengarah ke cabang itu. Pilih cabang yang panjang totalnya paling besar: itulah "backlink" Anda di sepanjang ranjang utama.
Untuk memperjelas ini, saya menawarkan beberapa pseudocode (belum diuji) . Input adalah seperangkat segmen garis (atau busur) S (terdiri dari aliran digital), masing-masing memiliki dua titik akhir yang berbeda mulai (S) dan ujung (S) dan panjang positif, panjang (S); dan p muara sungai , yang merupakan titik. Outputnya adalah urutan segmen yang menyatukan mulut dengan titik hulu yang paling jauh.
Kita perlu bekerja dengan "segmen bertanda" (S, p). Ini terdiri dari salah satu segmen S bersama dengan salah satu dari dua titik akhir, hal . Kita perlu menemukan semua segmen S yang berbagi titik akhir dengan titik pemeriksaan q , tandai segmen tersebut dengan titik akhir lainnya , dan mengembalikan set:
Procedure Extract(q: point, A: set of segments): Set of marked segments.
Ketika tidak ada segmen tersebut dapat ditemukan, Ekstrak harus mengembalikan set kosong. Sebagai efek samping, Ekstrak harus menghapus semua segmen yang dikembalikan dari set A, sehingga memodifikasi A itu sendiri.
Saya tidak memberikan implementasi Ekstrak: GIS Anda akan memberikan kemampuan untuk memilih segmen S berbagi titik akhir dengan q . Menandai mereka hanyalah masalah membandingkan mulai (S) dan akhir (S) dengan q dan mengembalikan mana dari dua titik akhir yang tidak cocok.
Sekarang kita siap untuk menyelesaikan masalah.
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
Prosedur "append (S, B0)" menempel segmen S di akhir array B0 dan mengembalikan array baru.
(Jika alirannya benar-benar pohon: tidak ada pulau, danau, kepang, dll - maka Anda dapat membuang langkah menyalin A ke A0 .)
Pertanyaan asli dijawab dengan membentuk penyatuan segmen yang dikembalikan oleh LongestUpstreamReach.
Untuk mengilustrasikannya , mari pertimbangkan aliran di peta asli. Misalkan itu didigitalkan sebagai koleksi tujuh busur. Busur a bergerak dari mulut di titik 0 (di atas peta, di kanan pada gambar di bawah, yang diputar) ke arah hulu ke pertemuan pertama di titik 1. Ini busur panjang, katakanlah 8 unit panjang. Arc b bercabang ke kiri (di peta) dan pendek, sekitar 2 unit. Arc c bercabang ke kanan dan panjangnya sekitar 4 unit, dll. Membiarkan "b", "d", dan "f" menunjukkan cabang sisi kiri saat kita pergi dari atas ke bawah pada peta, dan "a", "c", "e", dan "g" cabang lainnya, dan penomoran simpul 0 hingga 7, kita dapat secara abstrak menggambarkan grafik sebagai kumpulan busur
A = {a=(0,1), b=(1,2), c=(1,3), d=(3,4), e=(3,5), f=(5,6), g=(5,7)}
Saya akan kira mereka memiliki panjang 8, 2, 4, 1, 2, 2, 2 untuk sebuah melalui g , masing-masing. Mulutnya adalah simpul 0.
Contoh pertama adalah panggilan untuk Mengekstrak (5, {f, g}). Ini mengembalikan set segmen yang ditandai {(f, 6), (g, 7)}. Perhatikan bahwa simpul 5 berada pada pertemuan busur f dan g (dua busur di bagian bawah peta) dan bahwa (f, 6) dan (g, 7) menandai masing-masing busur ini dengan titik akhir hulu .
Contoh berikutnya adalah panggilan ke LongestUpstreamReach (0, A). Tindakan pertama yang dilakukan adalah panggilan untuk Mengekstrak (0, A). Ini mengembalikan set yang berisi segmen bertanda (a, 1) dan menghapus segmen a dari set A0 , yang sekarang sama dengan {b, c, d, e, f, g}. Ada satu iterasi dari loop, di mana (S, q) = (a, 1). Selama iterasi ini panggilan dilakukan ke LongestUpstreamReach (1, A0). Secara rekursif, ia harus mengembalikan urutan (g, e, c) atau (f, e, c): keduanya sama-sama valid. Panjang (M) yang dikembalikan adalah 4 + 2 + 2 = 8. (Perhatikan bahwa LongestUpstreamReach tidak mengubah A0 .) Di akhir loop, segmen atelah ditambahkan ke dasar aliran dan panjangnya telah ditingkatkan menjadi 8 + 8 = 16. Dengan demikian nilai pengembalian pertama terdiri dari urutan (g, e, c, a) atau (f, e, c, a), dengan panjang 16 dalam kedua kasus untuk nilai pengembalian kedua. Ini menunjukkan bagaimana LongestUpstreamReach hanya bergerak ke hulu dari mulut, memilih pada setiap pertemuan cabang dengan jarak terpanjang yang belum pergi, dan melacak segmen yang dilalui di sepanjang rute.
Implementasi yang lebih efisien dimungkinkan ketika ada banyak kepang dan pulau, tetapi untuk sebagian besar tujuan akan ada sedikit usaha yang sia-sia jika LongestUpstreamReach dilaksanakan persis seperti yang ditunjukkan, karena pada setiap pertemuan tidak ada tumpang tindih di antara pencarian di berbagai cabang: komputasi waktu (dan kedalaman tumpukan) akan berbanding lurus dengan jumlah total segmen.