網路流初步 sap演算法

2021-08-06 07:51:14 字數 3368 閱讀 9208

什麼是網路流?

請看下圖:

這是乙個有向圖,每一條邊都對應著兩個數值「/」前面的稱為流量,用f(

u,v)

表示,後面的稱為容量,用c(

u,v)

表示,網路中有兩個特殊的點,源點s和匯點t。

(一)容量限制,對於所有原圖中的變,均有f(

u,v)

≤c(u

,v)

(二)反對稱性,為了方便計算,我們定f(

u,v)

和f(v

,u) 中最多只有乙個是正數,可以都為負數,這樣定義的話,從u往v運三個物品,又從v往u運兩個,就相當於只從u往v運了乙個。

(三)留守恆性,從源點流出的流量一定等於流入t的容量。

定義乙個網路的流量為∑v

∈vf(

s,v)

,最大流問題就是在滿足三個性質的條件下,最大化

f 。

為了方便演算法的實現,我們定義乙個殘量網路,殘量網路的容量r(

u,v)

=c(u

,v)−

f(u,

v),通俗的講,就是現在還能有多少流量經過。

在一條從s到t的路線中,對於在這條路線中任意一條弧都有r(

u,v)

>

0 ,那麼這就是

每次我們找一條增廣路,並記錄下在這些殘量網路中最小的流量,然後將這些在這條增廣路中的殘量網路減去這個最小值,總流量加上這個值,同時也是滿足這三個性質的,就像這樣一直找,找到沒有增廣路為止。

假設這是原圖:

我們要求這個圖的最大流,首先找一條增廣路,s→

v1→v

2→t,

然後fl

ow+m

in,此時flow=8,然後原圖就變成下面這個樣子:

然後我們又找到一條增廣路,s→

v1→v

2→v3

→v4→

t,fl

ow加上

min ,此時flow=9。

接著再找一條增廣路,s→

v3→v

4→t ,flow加上mi

n ,此時flow=10。

此時在圖中不存在增廣路,演算法結束。

每一次也是找一條增廣路,只不過是最短的,其實時間複雜度基本是因為找增廣路的時間,如果將找增廣路的時間複雜度降下來,就好了。

所謂距離標號,就是指某個點到匯點的經過的最少的弧的數量,設i點的距離標號為di

,那麼滿足di

=dj+

1 的(i,j)弧叫作允許弧,且增廣時只走允許弧,那麼無論怎麼走都是最短路。初始化距離標號可以賦值為0。如何維護這個距離標號?

當在增廣過程中發現從某點出發沒有允許弧,那麼就將這個點的距離標號設為從它出發的所有的弧的距離標號的最小值加1。

對於每乙個點我們都儲存它的「當前弧」:初始化為第一條邊,查詢時直接從當前弧開始尋找,找到一條允許弧,就把它設為當前弧,改變距離標號的時候,將當前弧設為提供了最小標號的弧。

當一次距離標號時,出現了斷層,那麼就不存在增廣路。

別看演算法似乎很簡單,有很多細節。

now[i]表示當前弧。

const

maxn=1000+5;

var flow,aug,i,j,k,a,b,c,n,m,tmp,min:longint;

pre,g,vh,now,dis:array[0..maxn] of longint;

h:array[0..maxn,0..maxn] of longint;

bz:boolean;

begin

readln(m,n);

for i:=1

to m do

begin

readln(a,b,c);

inc(h[a,b],c);

end;

for i:=1

to n do

now[i]:=1;

vh[0]:=n;

aug:=maxlongint;

i:=1;

while dis[1]do

begin

bz:=false;

g[i]:=aug;

for j:=now[i] to n do

begin

if (h[i,j]>0) and (dis[j]+1=dis[i]) then

begin

now[i]:=j;

bz:=true;

if h[i,j]then

aug:=h[i,j];

pre[j]:=i;

i:=j;

if i=n then

begin

inc(flow,aug);

while i<>1

dobegin

dec(h[pre[i],i],aug);

inc(h[i,pre[i]],aug);

i:=pre[i];

end;

aug:=maxlongint;

end;

break;

end;

end;

if bz then

continue;

min:=n-1;

for j:=1

to n do

begin

if (h[i,j]>0) and (dis[j]then

begin

k:=j;

min:=dis[j];

end;

end;

now[i]:=k;

dec(vh[dis[i]]);

if vh[dis[i]]=0

then

break;

dis[i]:=min+1;

inc(vh[dis[i]]);

if i<>1

then

begin

i:=pre[i];

aug:=g[i];

end;

end;

writeln(flow);

end.

因為我水平有限,可能會有寫錯的地方,希望大家批評指正,多多包容,thank you for your patience.

網路流初步

問題 最大流問題 假設 把一些物品從結點s 源點 運送到t 匯點 可以從其他結點中轉。1.容量 對於一條邊 u,v 它的物品上限成為容量,記為c u,v 2.流量 實際運送的物品成為流量,記為f u,v 目標 最大化從s點流出的淨流量,即最大化 容量c與流量f滿足3個性質 1.容量限制 對g中的每條...

網路流最大流的sap 演算法

現在想將一些物資從s運抵t,必須經過一些中轉站。連線中轉站的是公路,每條公路都有最大運載量。每條弧代表一條公路,弧上的數表示該公路的最大運載量。最多能將多少貨物從s運抵t?這是乙個典型的網路流模型。為了解答此題,我們先了解網編流的有關定義和概論。若有向圖g v,e 滿足下列條件 1.有且僅有乙個頂點...

網路流之SAP演算法學習

終於決定開始學習網路流了 圖論演算法理論 實踐與應用 那本書講了很多關於求最大流的演算法,然後我就只挑了一種傳說中神奇的sap演算法學習。首先引入幾個新名詞 1 距離標號 所謂距離標號 就是某個點到匯點的最少的弧的數量 即邊權值為1時某個點到匯點的最短路徑長度 設點i的標號為level i 那麼如果...