費用流比較常用的做法有兩種: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 ...