就當模板啦…
不過這題第二問的構圖還是可以想一下的。。。
在殘量網路中把原來的邊全部加一遍,但是有費用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...