最大傳輸量
網路中有兩台計算機s和t,現在想從s傳輸資料到t。該網路中一共有n臺計算機,其中一些計算機之間連有一條單向的通訊電纜,每條通訊電纜都有對應的1秒鐘內所能傳輸的最大資料量。當其他計算機之間沒有資料傳輸時,在1秒鐘內s最多可以傳送多少資料到t?
將上述網路當做乙個有向圖。圖中每條邊e都有對應的最大可能的資料傳輸量。這樣就可以把問題轉為如下形式:
(1)記每條邊對應的實際資料傳輸量為f(e)。
(2)傳輸量應該滿足如下限制:
0<=f(e)<=c(e)
(3)資料在傳輸過程中既不會增加也不會減少,收到的資料量和發出的資料量應該相等。
目標是:最大化從s發出的資料量。
我們稱使得傳輸量最大的f為最大流,而求解最大流的問題為最大流問題。此外,我們稱c為邊的容量,f為邊的流量,s為源點,t為匯點。
(一)貪心演算法
(1)找一條s到t 的只經過f(e)(2)如果不存在滿足條件的路徑,則結束演算法。否則,沿著該路徑盡可能地增加,返回第(1)步。
但是得到的結果並非最優的。將最優結果和貪心演算法結果的流量求差,得到差值圖,可以發現,如果將差值為-1的流給推回去,而得到新的流。
於是將貪心演算法做如下改進:
(1)只利用滿足f(e)0的e對應的反向邊rev(e),尋找一條s到t的路徑。
(2)如果不存在滿足條件的路徑,則結束。否則,沿著該路徑盡可能地增加流,返回第(1)步。
注:我的理解:可以先按照貪心演算法,把結果求出來,然後把結果中流量不為0的邊加一條反向邊,繼續使用演算法,看還是否能求出一條新的路徑。
殘餘網路:考慮的f(e)0的e對應的反向邊rev((e)所組成的圖
下面是乙個ford-fulkerson演算法的鄰接表實現的例子,這裡沒有儲存f(e)的值,取而代之的是直接改變c(e)的值
//用於表示邊的結構體(終點,容量,反向邊)
struct edge;
vectorg[max_v];//圖的鄰接表表示
bool used[max_v];//dfs中用到的訪問標記
//向圖中增加一條從s到t容量為cap的邊
void add_edge(int from,int to,int cap)};
g[to].push_back};
//通過dfs尋找增廣路
int dfs(int v,int t,int f){
if(v==t) return f;
used[v]=true;
for(int i=0;iedge &e=g[v][i];
if(!used[g.to]&&e.cap>0){
int d=dfs(e.to,t,min(f,e.cap));
if (d>0){
e.cap=e.cap-d;
g[e.to][e.rev].cap+=d;
return d;
return 0;
//求解從s到t的最大流
int max_flow(int s,int t){
int flow=0;
for(; ;){
memset(used,0,sizeof(used));
int f=dfs(s,t,inf);
int(f==0) return flow;
flow+=f;
最大流問題
暫時最大流問題我就先掌握這一種演算法吧 基本的最大流問題 ek演算法 基於bfs 每一次bfs更新一條路徑,雖然都會入佇列,但是由於以下條件保證點不會交叉,所以只有一條到終點的路徑會更新流量。if res v map u v flow u v 注意更新flow矩陣的時候是這樣的 while u st...
最大流問題
具體的最大流問題定義 術語以及特性,前人已經描述的很詳細了 我們需要注意以及幾個方面 增益路徑的生成次序如果不恰當,會對方法的效率有巨大的影響。如下 其中u代表某個大正整數。如果沿著路徑1 2 3 4對流量0進行增益,得到 b 中值為1的流量 接著沿著路徑1 3 2 4對流量0進行增益,得到 c 中...
最大流問題
對最大流問題比較感性的認識,要看證明還是要看演算法導論的相關章節。最大流問題 給定乙個有向圖,一般情況下邊的值為整數,定義不直接相連的節點間的邊值為0,如果有節點i和j直接由多條邊,則將這些邊合併為一條,值取和。則若i到j有邊,則j到i的邊為0,這些邊稱為反向邊。定義其中的兩個點位源點和匯點,則這個...