Үндэсний програмчлалын тэмцээн 4-н сарын 10-н 11-нд болсон. Одоогоор надад бүх бодлогууд нь ирээгүй байна, гэхдээ энэ тэмцээнд миний нэг бодлого сонгогдсон ба уг бодлогыхаа анализыг хийнэ. Гэснээс ганц ч баг бодоогүй байна лээ.
Үүнээс өмнө товчхон нетворк флов - урсгалын бодлогыг тайлбарлая.
Урсгалын бодлого маш олон янзаар гарч ирдэг. Жишээ нь хотын замын сүлжээ өгөгдсөн байгаа8 мөн зам бүр дээр явах машины тоог хязгаартай, энэ хязгаарууд нь бидэнд өгөгдсөн. Тэгвэл А гэсэн хотоос В гэсэн хотруу хамгийн ихдээ хэдэн машин явуулж болох вэ? Энэ бодлогыг Maximum Flow гэж нэрлэдэг.
Өөр нэгэн жишээ, Хотын сүлжээ замууд өгөгдсөн. Та тодорхой хэдэн тооны зам устгаж А В гэсэн 2 хотыг хооронд нь хүрэх боломжгүй болгох гэж байгаа. Зам бүрийг устгахад тодорхой зардалтай, таны даалгавар уг гарах зардалыг хамгийн бага байлгах юм. Энэ бодлогыг Minimum cut гэж нэрлэдэг.
Дээрх 2 бодлого 2уул өөр харагдаж байгаа ч, гайхалтай теорем, хариу яг ижил гардаг. Өөрөөр хэлвэл ямар нэгэн эерэг жинтэй чиглэлт графын хувьд, А оройгоос В оройн хувьд MaximumFlow = MinCut байдаг.
Жишээг зургаар харуулая.

s гэсэн оройгоос t гэсэн орой хүрэв хамгийн их урсгал 23 буюу дараах замуудыг ашигласан байх нь.

Одоо тэгвэл мөн 2 оройн хоорондахь MinCut-г олоё. Дээрх хэлсэн теоремоор хамгийн их урсгалтай тэнцүү 23 буюу дараах замуудыг устгах нь.

Алгоритмаа тайлбарлая
Өгөгдсөн графын хувьд s-с t хүрдэг ямар нэгэн замыг авч үзье, мөн үүнийгээ дэд зам гэж нэрлэе. Энэ нь бидэнд уг замд ашиглагдаж байгаа жингүүд бас мэдэгдэж байгаа ба эдгээрийгээ w1 w2 ... wk гэе. Тэгвэл энэ олсон замаар хамгийн ихдээ хэдий хэмжээний урсгал урсуулж болох вэ? энэ асуултын хариу min(w1, w2, ..., wk). Энэ хариуг урсгалын дэд хэмжээ гэе.
Дээрх жишээний хувьд дараах дэд замууд байж болох ба тухай бүрийх нь дэд урсгалууд нь хамгийн бага утгаад нь байхнээ.

Алгоритмд ашиглагдах ба нэгэн ухагдахууныг тайлбарлая
Ирмэгийг эргүүлэх
C(u -> v)-ээр хоёр хөрш u, v оройн хоорондахь боломжит урсгалын хэмжээг тэмдэглэе, мэдээж энэ чиглэлтэй шүү.
Тэгвэл ямар нэгэн дэд урсгал f уг хоёр хөрш оройгоор дамжвал
C(u -> v)-г f-ээр багасгаад
C(v -> u)-г f-ээр нэмэгдүүлэе.
Ингэх нь юун ашигтай вэ гэхээр, бодоо үзээрэй, ямар нэгэн урсгалыг явуулчаад буцаана гэдэг нь энэ урсгалыг ашиглаагүйтэй адил.
За одоо дараах үйлдэлийг боломжгүй болтол нь хийе.
0 flow = 0
1 Хэрэв олдвол ямар нэгэн дэд зам ол, DFS.
2 Дэд урсгалыг ол flow-н утгыг уг утгаараа нэмэгдүүл.
3 Дэд зам-г бүрдүүлж байгаа бүх (u -> v)-н хувьд C(u->v)-г дэд урсгалаар багасгаж, C(v->u)-г дэд урсгалаар нэмэгдүүл.
4 1рүү оч.
За хө ингээд болоо. Дээрх алгоритмыг Ford-Fulkerson гэдэг, олсон хүнийх нь нэр. Хугацааны үнэлгээний хувьд дэд замыг O(V+E), мөн бид ядаж 1 урсгалыг дамжуулж байгаа тэгэхээр O((V+E)*flow). Энэ ер нь бол ихэнх тохиолдолд хангалттай үнэлгээ уг бодлогын хувьд.
MinCut бодлогын хувьд утгыг нь тэгээд олчихдог юм байж. Яаж устгагдсан ирмэгүүдийг олох вэ? энэ бодлогыг энэ талаар судлаж сонирхож байгаа хүмүүст өөрсөдөд нь үлдээе, энгийн амархан олдно. Туслах үүднээс, дээр хэрэглэгдэж байгаа С гэсэн хүснэгт бодлогын хариуг олсны дараа ямархуу байдалтай болж гэдэгийг ажиглаараа, энэ хүснэгтээс ирмэгийг олно. Дараа дараагийхаа постоор хэрхэн алгоритмаа сайжруулах мөн жишээ бодлогуудын бодолт харуулая.
За одоо өөрийн бодлогоруугаа ороё.
Бодлогын өгүүлбэрийг энд дарж уншина уу.
Бодлого бол s гэсэн оройгоос t гэсэн орой хүртэл хоорондоо аль ч ирмэг оройгоор огтлолцоогүй байх 2 зам олох ба замуудын нийлбэр хамгийн бага байх ёстой. Энэ бодлогонд s=1, t=V гэж бэхлэсэн байгаа.
d(s,u)-ээр s оройгоос u хүрэх хамгийн богино замын хэмжээг тэмдэглэе. w(u,v)-ээр хэрэв u, v гэсэн орой хоорондоо u->v гэх чиглэлээр холбогдсон хөрш оройнууд бол тухайн ирмэгийн жинг тэмдэглэе.
Одоо s-ээс богино замын алгоритм Дижкстра хийн богино замуудыг олоё. Ингэхдээ бид s-дээр оройтой Т гэсэн модыг байгуулж чадна. Уг модон дээр байгаа u гэсэн орой бүрийн хувьд бид s->u богино замыг мэдэж чадна, энд мэдээж эд нар нь хөрш байх албагүй. P1-ээр T модондээр орших s->t замыг гэж үзье, бас мод байна шүү. Одоо графыхаа бүх w(u, v) ирмэгийн хувьд дараах өөрчлөлтийг хийе. w'(u,v) = w(u,v) − d(s,v) + d(s,u). Ингэхдээ Т модондээр байгаа бүх ирмэгүүдийн жинг 0 байхаар мөн Т модонд харъяалагдахгүй ирмэгүүдийн хувьд сөрөг тоо байхааргүй зохицуулаарай.
Одоо байгаа мэдээллээ ашиглан дахин шинэ граф байгуулая. Шинэ граф нь s-рүү орсон ирмэгийг хасна, мөн P1 модонд харьяалагдаж байгаа 0 утгатай ирмэгүүдийн хувьд чиглэлийг нь урвуулна.
Шинэ граф дээрээ дахин s-ээс эхлэн дахин Дижкстра хийн s->t богино замыг илэрхийлэх модыг олоод P2 гэе. P1 P2 хоюуланд нь харьяалагдах урвуулсан ирмэгийг хасая. Үлдсэн граф бодлогын хариу! энд 0 урттай цикл оршин байж болно. Бодлогын бүтэн хариу утга юу байх вэ? үүнийг уншигчдад үлдээе.
UPDATE
Жишээ болгон алгоритмын ажиллах процессыг доорх зурган жишээгээр харууллаа. Одоо бүр ойлгомжтой байх.

Бодлогыг ЭНД дарж бодно уу.
Нэгэнд энэ пост маань урсгалаар эхэлсэн учир энэ бодлогыг урсгалаар бодогдож болно, би гэхдээ одоо постоо үргэлжлүүлж чадахгүй нь, бодоход туслах нэг санаа нэмээд дараагийн урсгалын жишээ бодлогууд, нэмэлт сайжруулалт дээр бодолтыг тайлбарлая.
Vk гэсэн орой бүрийн хувьд (Vk(in) -> Vk(out)) гэсэн өөрчлөлт хийн графаа өргөтгөөд үз, ийм техник ер нь бол огтлож болохгүй гэсэн хязгаарлалтад тусладаг.
Жич: Монголоороо алдаатай бичсэн бол уучлаарай.