網路流
題記:網路流是最近講過的最迷演算法……
網路流(network-flows)是一種模擬水流的解決問題方法,與線性規劃密切相關。非常重視選手在網路流上的建模技巧,畫圖是非常關鍵的。
1、最大流
問題引入:
有n條溝渠,與水坑s、t相連,匯聚成m個點,第i條溝渠的水流的流量為c[i],每乙個點的流入量和流出量都要相等,水由原點水坑s,匯聚到水坑t,求可以有多少水可以匯聚過去。
(poj. 1273)
如圖所示:
可以將問題進行如下整理:
(1)用c[e]表示每條邊最大的可能流量
(2)每條邊對應的實際流量為f[e]
(3)根據條件,可知所有的f[e]<=c[e]
(4)目標是最大化從s發出的水流量
問題分析:
很容易會想到貪心演算法,但很明顯,貪心不一定是最優的,如果從某乙個地方,流過全部的水,那麼從其他地方便不能再用這條溝渠了。
舉個例子:如圖1為某個資料用貪心演算法所得的值,由某一條溝渠開始流過,盡可能地多流,最後得出最多的水為10。
但最優解應該是圖2,正確答案為11。那麼是**多了了呢?
不防用正解與貪心做法流過水的差值做乙個對比,通過對流量的差可以發現,我們通過將原先得到的流給推回去(圖中的-1部分),而得到了新的流,從而達到最優解。
為什麼貪心得不到最優解:
當貪心得到一定的值的時候,那麼這條溝渠便不在能用,把很多原來可能是可以流過去的水給卡在那裡,而匯聚不到t點,用wyy的說法來說,可能會「擋路」。
在這裡大概講一下,畫幾個樣例便會明白。
最大流的定義:
我們稱使得傳輸量最大的f為最大流,而求解最大流的問題稱為最大流問題。而我們學的是增廣路演算法。
關於反向邊的建立:
如上面說到的正解,是通過把流推回去而得到的,這麼說明,需要有乙個反悔的機會,即不選擇流過原來那麼多水,這下反向邊就很關鍵了。
圖中曲線為建立的反向邊,直線為正向邊。當水流過正向邊的時候,正向邊還可以流過的水量自然要減去已經流過的f,而同時也可以返回f的流水,也就是給反向邊的邊權變為f。
這樣的好處是,下一次再掃路徑發現會有更優時,可以倒退回去,當然,不管是走反向邊還是走正向邊,都要把另一條邊加上流過的水量,以便與以後反悔。
心情增廣路的定義(注意不是針管路哦):
我們所考慮的f[e]0的e對應的反向邊所組成的圖稱為殘餘網路,並稱殘餘網路上s->t的路徑為增廣路。
ford和fulkerson迭加演算法:
便是在貪心演算法的基礎上的迭代。
把各條弧上單位流量的費用看成某種長度,用求解最短路問題的方法確定一條自v1至vn的最短路;在將這條最短路作為可擴充路,用求解最大流問題的方法將其上的流量增至最大可能值;
而這條最短路上的流量增加後,其上各條弧的單位流量的費用要重新確定,如此多次迭代,最終得到最大流。
具體實現:
我採用的是陣列模擬指標的方法,畢竟指標不怎麼會用,而用vertor怕不能準確地找到它的反向邊。
陣列模擬指標因為是按順序儲存,把正向邊標為0,反向邊標為1,先存正向邊,再存反向邊。
「無限」跑dfs,直到找不到一條能由s=1到t=n的路徑。每一次在路徑上取最小的流量(mi),這樣可以確保每一段路減去mi不會為負數。同時要更改此時還可以流過的流量(va),因為已經流過了這麼多水,要用原來的va-mi,同時要把對面的邊(正邊找反邊,反邊找正邊)加上這麼多(可後悔的值)。
這裡順便說一下怎麼找對面的邊:要找當前的反向邊時,只用加一即可,如果找正向邊,就減一。這樣會好理解一點,因為他們是按順序儲存的!!也可以用異或,**更簡潔。
時間複雜度:
最多進行深度為f次深度優先搜尋,所以其複雜度為o(f|e|),最壞的情況基本上不存在。所以在多數情況下,及時得出的複雜度偏高,實際運用中還是比較快的。
#include
#include
#include
#include
using namespace std;
const int maxn=205,oo=10000005;
int n,m,a,b,c,s,t,ans;
int cur=-1,head[maxn];
bool v[maxn];
struct water
edge[2*maxn];
void add(int from,int to,int va,int type)
int dfs(int now,int mi)
}
h=edge[h].next;
} return 0;
} int main()
while(1)
cout<
<
網路流(最大流)
我們圍繞一道題來講解吧 藍橋杯 演算法訓練 網路流裸題 首先,何為網路流最大流問題?可行流 對於每條路線 u,v 上給定乙個實數f u,v 滿足 0 f u,v c u,v 則稱f u,v 為路線 u,v 的流量。而對於一組具有源點和匯點,且總流出量 總流入量,則稱為網路中的一條可行流。拿例子來說 ...
網路流 最大流
dinic 最大流 head x 從0開始記 這樣便於找反向邊 異或即可 當前弧優化 include include include include include include include define ll long long define ull unsigned long long d...
網路流最大流
源點 起始點 匯點 目標點 流 從源點到匯點的一條路徑 容量 每條管道允許通過的最大流量 流量 通過一條邊的水的實際體積 最大流等於最小割 從起點到終點的一條路徑 尋找從s到t的一條增廣路 在紅色的路線裡,路徑的一條最小流量是3,那麼這條路徑上的邊都減去3,同時反向邊加上3 這條增廣路的乙個流量是3...