最小割(uva1515-水塘)

輸入一個(gè)h行w列的字符矩陣,草地用“#”表示,洞用“.”表示。你可以把草改成洞,每格花費(fèi)d,也可以把洞填上草,每格花費(fèi)f。最后還需要在草和洞之間修圍欄,每條邊花費(fèi)b。整個(gè)矩陣的第一行/列,最后一行/列必須都是草。求最小花費(fèi)。2<=w,h<=50 1<=d,f,b<=10000

想要理解這道題的解法,首先需要建立正確的“割”的概念。
事實(shí)上,這道題糾正了我對(duì)“割”的理解……

關(guān)于割的討論

以下摘自算法導(dǎo)論
流網(wǎng)絡(luò)G=(V,E)中的一個(gè)切割(S,T)將結(jié)點(diǎn)集合V劃分為S和T=V-S兩個(gè)集合,使得s∈S,t∈T。
切割(S,T)的容量是:
c(S,T)=\sum_{u∈S}\sum_{v∈T}c(u,v)

算法導(dǎo)論中定義了s-t割,即流網(wǎng)絡(luò)中的源點(diǎn)s要在S集中,匯點(diǎn)t要在T集中。我們給出一個(gè)流網(wǎng)絡(luò),除了源點(diǎn)s和匯點(diǎn)t,還有a、b、c三個(gè)中間結(jié)點(diǎn)。
算法導(dǎo)論中是從點(diǎn)的角度定義割的,而我們應(yīng)用時(shí)一般從邊的角度考慮,即用割斷的邊的集合表示一個(gè)割。
那么問題來了,如下圖所示,我們割斷了邊s→a、b→c,使得s和t不連通,那么邊集{s→a,b→c}是這張網(wǎng)絡(luò)圖的割嗎?

這是一個(gè)割嗎?

它并不是一個(gè)割,如果我們定義割集是組成割的容量的邊的集合的話。由我們對(duì)割的一般認(rèn)知,去掉割中的所有邊,則S、T集不連通(確切地說,S無法連向T,而T可以連向S,這是割的容量的定義所內(nèi)含的),所以對(duì)于這張圖,顯然S={s、a、b},T={c、t},如此s→a這條邊就是S集內(nèi)部的,不是橫跨S、T的邊,不是割的流量的組成部分。

去掉它,正確的割如下圖:

正確的割1

或者在割中新加入一條邊b→a:

正確的割2

這個(gè)割有一點(diǎn)奇怪,雖然我們把所有點(diǎn)劃分成了S集{s、b},T集{a、c、t},并且割斷且僅割斷了所有滿足"u∈S,v∈T"的邊u→v,但是點(diǎn)a與匯點(diǎn)t卻不連通!

事實(shí)上,割的定義中從來就沒有說過,T集中的點(diǎn)都能流向匯點(diǎn)t,或者源點(diǎn)s能流向S集中的所有點(diǎn)。

換個(gè)角度來理解,每當(dāng)你選擇一條有向邊u→v割斷時(shí),u及所有流向u的點(diǎn)將被自動(dòng)地劃入S集,v及v流向的所有點(diǎn)被自動(dòng)地劃入進(jìn)T集。如此切割若干條邊后使得最終的圖邏輯自洽,即沒有哪個(gè)點(diǎn)既屬于S也屬于T(在第一幅圖中,a就是一個(gè)邏輯矛盾的點(diǎn)),這樣的一個(gè)切割邊集,才是一個(gè)正確的割。

用最大流算法跑出的最小割當(dāng)然也是一個(gè)正確的割,而且是所有正確的割中容量最小的那一個(gè)。

回到題目上來

題目可以這樣理解:每個(gè)格子是一個(gè)結(jié)點(diǎn),整張圖是一張有向圖(流網(wǎng)絡(luò)),每個(gè)格子擁有指向它上下左右4個(gè)鄰居的4條有向邊。我們需要把所有的格子劃分成兩個(gè)陣營:“草”或“洞”,并且選擇一些邊建立圍欄(割斷),使得“草”中的任何一點(diǎn)不能流向“洞”中任何一點(diǎn),反之亦然。
這里有一點(diǎn)需要注意,我們建模時(shí)兩個(gè)結(jié)點(diǎn)之間有一來一回兩條邊,所以建圍欄時(shí)相當(dāng)于這兩條邊同時(shí)割斷了,因此我們不妨將目標(biāo)修改為:割斷一些有向邊,使得“草”中任一點(diǎn)不流向“洞”中任何點(diǎn),而不必關(guān)心“洞”中的點(diǎn)能否流向“草”中的點(diǎn)。這樣做的極大好處在于:對(duì)于一對(duì)相鄰點(diǎn)u、v,如果將u劃分為草,v劃分為洞,那么就割斷u→v,反之就割斷v→u。
為了建立最小割模型,引入源點(diǎn)s,將它連向所有初始的草點(diǎn),并設(shè)這些邊容量為d(草轉(zhuǎn)洞的代價(jià)),引入?yún)R點(diǎn)t,將所有初始的洞點(diǎn)連向它,容量設(shè)為f(洞轉(zhuǎn)草的代價(jià)),并把之前建立的那些網(wǎng)格圖上的有向邊的容量設(shè)為b(建圍欄的代價(jià))。跑s-t最小割,所得最小割的容量即是最小總代價(jià)。
為什么呢?每當(dāng)割斷一條鄰居間的邊時(shí),就做了一次決策(哪邊劃入草,哪邊劃入洞),每一組對(duì)于全局的決策都能夠確定出一個(gè)割出來,不會(huì)遺漏情況。另一方面,由于s連向所有初始的草,如果它在決策中被劃入洞,那么s連向它的邊就一定會(huì)被切斷,否則這個(gè)割是不自洽的,轉(zhuǎn)換的代價(jià)也即是這條邊的容量就因此被計(jì)算進(jìn)去了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。