bzoj1834 最大流 最小費用最大流

2021-07-01 20:14:37 字數 4316 閱讀 9507

就當模板啦…

不過這題第二問的構圖還是可以想一下的。。。

在殘量網路中把原來的邊全部加一遍,但是有費用w,容量無限大,一開始的邊還是費用為0

新建乙個源點s,s向1連一條邊,容量為k,費用為0,保證這條邊滿流,就有最小費用了。

program bzoj1834;

type point=record

s,t,cap,flow,o,w,next:longint;

end;

var p,l,n,m,k,c,i:longint;

v1:array[0..1010]of boolean;

edge:array[1..30010]of point;

head,d:array[0..1010]of longint;

b:array[1..10000000]of longint;

u,v,w:array[0..5010]of longint;

procedure

add(u,v,c,w:longint);

begin

l:=l+1;

edge[l].s:=u;

edge[l].t:=v;

edge[l].cap:=c;

edge[l].flow:=0;

edge[l].o:=l+1;

edge[l].w:=w;//費用

edge[l].next:=head[u];

head[u]:=l;

l:=l+1;

edge[l].s:=v;

edge[l].t:=u;

edge[l].cap:=c;

edge[l].flow:=c;

edge[l].o:=l-1;

edge[l].w:=-w;

edge[l].next:=head[v];

head[v]:=l;

end;

function

min(a,b:longint):longint;

begin

if athen min:=a else min:=b;

end;

function

bfs:boolean;

var top,tail,p:longint;

begin

d[1]:=1;

top:=1;tail:=1;

b[1]:=1;

fillchar(v1,sizeof(v1),false);

v1[1]:=true;

repeat

p:=head[b[top]];

while p<>-1

dobegin

if (v1[edge[p].t]=false)and(edge[p].cap>edge[p].flow) then

begin

v1[edge[p].t]:=true;

d[edge[p].t]:=d[b[top]]+1;//層次

tail:=tail+1;

b[tail]:=edge[p].t;

end;

p:=edge[p].next;

end;

top:=top+1;

until top>tail;

exit(v1[n]);

end;

function

addflow

(x,maxflow:longint):longint;

var p,o:longint;

begin

if (x=n) or (maxflow=0) then

exit(maxflow);

addflow:=0;//這個一定要寫!!

p:=head[x];

while p<>-1

dobegin

if (d[edge[p].t]=d[x]+1)and(edge[p].cap>edge[p].flow) then

begin

o:=addflow(edge[p].t,min(maxflow,edge[p].cap-edge[p].flow));

if o>0

then

begin

inc(edge[p].flow,o);

dec(edge[edge[p].o].flow,o);

maxflow:=maxflow-o;

addflow:=addflow+o;

if maxflow=0

then

break;

end;

end;

p:=edge[p].next;

end;

end;

function

dinic:longint;

begin

dinic:=0;

while bfs do

dinic:=dinic+addflow(1,maxlongint);

end;

function

spfa:longint;

var cost,top,tail,i,p:longint;

pre,re:array[0..1010]of longint;

flag:array[0..1010]of boolean;

d:array[0..1010]of longint;

mm:longint;

begin

cost:=0;

while

true

dobegin

top:=1;tail:=1;

b[1]:=0;

for i:=0

to n do d[i]:=maxlongint;

d[0]:=0;//流量

fillchar(pre,sizeof(pre),0);

pre[0]:=-1;

fillchar(re,sizeof(re),0);

fillchar(flag,sizeof(flag),true);

flag[0]:=false;

repeat

p:=head[b[top]];

while p<>-1

dobegin

if (edge[p].cap>edge[p].flow)and(d[b[top]]+edge[p].wthen

begin

d[edge[p].t]:=d[b[top]]+edge[p].w;

pre[edge[p].t]:=b[top];

re[edge[p].t]:=p;

if flag[edge[p].t] then

begin

flag[edge[p].t]:=false;

tail:=tail+1;

b[tail]:=edge[p].t;

end;

end;

p:=edge[p].next;

end;

flag[b[top]]:=true;

top:=top+1;

until top>tail;

if d[n]=maxlongint then

break;

i:=n;

mm:=maxlongint;

while pre[i]<>-1

dobegin

mm:=min(mm,edge[re[i]].cap-edge[re[i]].flow);

i:=pre[i];

end;

i:=n;

while pre[i]<>-1

dobegin

inc(edge[re[i]].flow,mm);

dec(edge[edge[re[i]].o].flow,mm);

cost:=cost+mm*edge[re[i]].w;

i:=pre[i];

end;

end;

spfa:=cost;

end;

begin

read(n,m,k);

for i:=0

to n do head[i]:=-1;

for i:=1

to m do

begin

read(u[i],v[i],c,w[i]);

add(u[i],v[i],c,0);

end;

write(dinic,' ');

//最小費用最大流

for i:=1

to m do

add(u[i],v[i],maxlongint,w[i]);

add(0,1,k,0);

writeln(spfa);

readln;readln;

end.

BZOJ 1834 網路擴容 最大流 最小費用流

題目大意 給定一張有向圖,每條邊都有乙個容量c和乙個擴容費用w。這裡擴容費用是指將容量擴大1所需的費用。求 1 在不擴容的情況下,1到n的最大流 2 將1到n的最大流增加k所需的最小擴容費用。思路 第一問直接求費用流,第二問,在第一問的殘餘網路上,對於每條邊額外加上inf容量費用為w的邊,限制最大流...

bzoj 1834 網路流(最大流 費用流)

題意 n個點,m條無向邊,每條邊有乙個容量和擴容費用 容量擴大1的費用 2個詢問 1 不擴容下的1 n最大流 2 將最大流增加k的最小費用 強行湊出的網路流經典題麼 23333 對於第一問,裸跑最大流即可 第二問的建圖還是很不錯的,一開始認為,應該重新建邊,容量為k,費用是給題目給的。but,too...

BZOJ 1834 網路擴容 最大流 費用流

對於第一問,直接求最大流。對於第二問,建源點s和匯點t,s連1容量為inf,費用為0的邊,n連t容量為最大流 k,費用為0的邊。這樣就把最大流限制為最多增加k了。限制需要求擴充的最小費用,原圖的邊多連一條容量為inf,費用為增容費用k的邊。跑一遍費用流即是答案。include include inc...