ZKW,SPFA費用流模板

2021-08-03 07:42:22 字數 2050 閱讀 1662

費用流比較常用的做法有兩種:spfa費用流和zkw費用流

兩種費用流的基本做法相同:找到費用最小的路,不斷增廣到不能增廣為止

正確性很顯然,因為每次都找費用最小的路,所以費用一定最小,因為增廣到不能增廣才停止,所以一定是最大流

費用流打起來和理解起來很簡單,就是通過spfa找到費用最小的路,並把這條路上的每條邊的流量都減去這整條路的流量最小值,不斷迴圈直到找不到增廣路位置

缺點也很顯然:在稠密圖中速度太慢

找不到c++的了,發乙個幾年前碼的pascal吧

function

spfa:boolean;

var i,j,k,l:longint;

begin

for i:=1

to t do

begin f[i]:=-maxlongint+100000;bz[i]:=false;end;

i:=0;j:=1;

d[1]:=s;bz[s]:=true; f[s]:=0;

while ido

begin

inc(i);

l:=d[i];

for k:=1

to t do

begin

if (a[l,k]>0)and(f[l]+c[l,k]>f[k]) then

begin

f[k]:=c[l,k]+f[l];

from[k]:=l;

if bz[k]=false

then

begin

bz[k]:=true;

inc(j);d[j]:=k;

end;

end;

end;

bz[l]:=false;

end;

exit(f[t]>0);

end;

begin

while spfa do

begin

i:=t; mi:=maxlongint;

while i<>s do

begin

j:=i;i:=from[i];

mi:=min(mi,a[i,j]);

end;

i:=t;

while i<>s do

begin

j:=i;i:=from[i];

dec(a[i,j],mi);inc(a[j,i],mi);

ans:=ans+c[i,j];

end;

end;

writeln(ans);

end.

這種做法略高階,理解起來有一點難度

它和sap的做法有點像,sap是只走高度相差為1的點,zkw只走費用差最小的點

也就是說,zkw中的費用相當於sap中的高度

設dis[x]表示x到t的最短費用

假設有一條路從x->y

那麼dis[x]-fee[x,y]=dis[y]

也就是每次在已經走的點中選乙個高度(dis)公升高最小的作為下次增廣的邊

我語文能力太差,直接上標吧

putin是連邊

#include

#include

#include

#include

using namespace std;

int n,m,s,t,last[m],next[m*10],to[m*10],date[m*10],tot=1,bz[m],a[n][n];

db fee[m*10],dis[m];

void putin(int x,int y,int z,db f)

int dg(int x,int z)

}return jy;

}bool change()

if(abs(minh-inf)<0.000001) return 0;

if(minh<-1) return 0;

fo(x,1,t) if(bz[x]) dis[x]+=minh;

return 1;

}int main()

費用流模板

const int oo 1e9 無窮 const int mm 11111111 邊 const int mn 888888 點 int node,src,dest,edge int ver mm flow mm cost mm nex mm int head mn dis mn p mn q m...

費用流(模板)

費用流模板 spfa不停找當前從s到t的最小費用路,然後重新整理最大流 這裡把每條邊的cost為0,同樣就可以求最大流,不過有點慢 include include include include include include include include include include incl...

費用流模板

我借鑑了一些大神的 也就是他們經常用的模板。費用流模板 include includeusing namespace std const int oo 1e9 const int mm 11111 const int mn 888 int node,src,dest,edge int ver mm ...