網路流之最大流
一、 問題引入。
有n個排水口,不同的排水口之間有m條水管連線,水一開始從源點s流出,最終到達t。每條邊(水管)都有乙個最大的流量。除了s,t外,每個排水口的流入量都要等於流出量,詢問最多能有多少水到達終點t ?
如圖所示:
(即poj 1273)
可以將問題進行如下整理:
(1)用c[e]表示每條邊最大的可能流量
(2)每條邊對應的實際流量為f[e]
(3)根據條件,可知所有的f[e]<=c[e]
(4)目標是最大化從s發出的水流量
二、問題分析:
很容易會想到貪心演算法,就是不斷地從源節點s出發尋找能到達t的路徑,能流就流,一路上對c[e]取min,流了之後將路上的c[e]減掉此次的流量mina。直到找不到路徑為止。
但是,其實這樣的演算法是不正確的。
以下是《挑戰程式競賽》中的反例。
左圖為貪心演算法執行出的結果,答案為10,但是右圖答案為11。不妨找找這兩圖流量的差來分析原因。
通過分析反例,可以發現,我們在流過某一條邊之後,可能會導致以後無法經過此邊。如左圖,s->1->2->t使得s->2->t無法走,而且還限定了s->1->3->t的流量。因此,一開始就流s->1->2->t很可能不是最優的。
因此,我們需要給每條邊乙個「反悔」的機會,要考慮到實際上某次不流這條邊的情況。
在此基礎上,增廣路演算法橫空出世。下文介紹其中的一種——ford-fulkerson演算法。
二、 ford-fulkerson演算法
我們在原先演算法的基礎上,將演算法進行如下改進:
我們給每條邊增加一條反向邊,初始上限流量為0。
如前文的貪心演算法那樣,不斷尋找s到t的路徑。某一條邊為e,反向邊為g 。每次找到一條可行路徑(流量為 res),則ans+=res,並將路徑上邊的上限流量減去res, 其相對的反向邊的上限流量加上res。直到找不到一條流量大於0的路徑,則停止演算法。
將這一演算法應用為樣例中:
很顯然,答案正確。
為何?增加反向邊的意義,其實就是給了每條邊乙個反悔的機會。比如說第一次流過了邊e,又流了一次其反向邊g,則邊的上限流量就又回到了初始狀態,相當於沒有流。每條邊都可以流,也可以反悔,就保證了演算法的正確性。
三、 複雜度分析
設最大流流量為f,則最壞的時間複雜度為o(f|e|)
不過實際應用中,還是很快的。
四、 **實現
poj1273模板題源**:
#include#include#includeusing namespace std;
const int maxn=205,inf=1e7+5;
int m,n,cur,s,t,a,b,va;
int head[maxn],v[maxn];
long long ans;
struct wyy
edge[2*maxn];
void add(int from,int to,int va,int type)
int dfs(int now,int mina)
}
h=edge[h].next;
}return 0;
}int main()
while(1)
cout<
}return 0;
}
網路流之最大流
因為網上介紹網路流和最大流理論的文章非常的多,也都解釋的非常清晰並附帶 再加上繪圖技術不佳,語文表達極差,就只講解一下程式實現部分。想看理論講解及演算法正確性證明的讀者可以上網搜一搜,這裡推薦一篇部落格,鏈結如下 那麼,既然網上的資源那麼多,為什麼還要寫這篇部落格呢?一是為了湊數做筆記,二是網上的許...
網路流之 最大流
最大流演算法是網路流中基礎的演算法,解決的方法有很多,比如ek,dinic,sap等等,在這裡介紹一下ek演算法。從源點s開始廣度優先尋找一條到t的路徑,計算出這條路徑的最大流量 短板效應 l,回溯,將這條路徑的每條邊的最大流量減去l,然後新增反向邊,容量為l,網路流的最大流max l。當找不到從s...
網路流之最大流
通俗易懂的說就是從乙個起點運輸貨物到終點,但是途中運輸的容量有各自不同的限制,有大有小,起點和終點分別用s,t表示,其中有中轉點,運輸路線和運輸容量。用圖論中的有向圖中g v,e 來表示,每條邊 u,v 代表運輸路徑,邊上的權值代表運輸容量限制,各個節點表示每乙個中轉點。每乙個運輸路線上運輸量不能超...