網路流之最大流

2021-08-06 04:12:31 字數 2058 閱讀 1203

網路流之最大流

一、 問題引入。

有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 代表運輸路徑,邊上的權值代表運輸容量限制,各個節點表示每乙個中轉點。每乙個運輸路線上運輸量不能超...