看题面就看出是费用流,但和普通费用流有所不同。
因为是乘法统计,所以反向边要设为倒数,spfa找乘积最大路,统计流的时候也要用乘。
注意精度问题,要不然就可能出现一条边和它的反向边乘起来>1了,spfa就会爆炸。
代码
type
edge=^edgenode;
edgenode=record
t,c,f:longint;
w:double;
next,rev:edge;
end;
var
n,k,i,j,x,y,z,v:longint;
w,ans,u:double;
o1,dist:array[0..310]of double;
o2:array[0..310]of longint;
con,lj:array[0..310]of edge;
visit:array[0..310]of boolean;
dl:array[0..90010]of longint;
const res=1e-12;
function min(x,y:longint):longint;
begin
if x>y then exit(y)
else exit(x);
end;
procedure ins(x,y,z:longint;w:double);
var
p:edge;
begin
new(p);
p^.t:=y;
p^.f:=0;
p^.c:=z;
p^.w:=w;
p^.next:=con[x];
con[x]:=p;
new(p);
p^.t:=x;
p^.f:=0;
p^.c:=0;
p^.w:=1/w;
p^.next:=con[y];
con[y]:=p;
con[x]^.rev:=con[y];
con[y]^.rev:=con[x];
end;
procedure spfa;
var
head,tail,i,flow,minf:longint;
p:edge;
begin
ans:=1;
flow:=0;
while flow<k do
begin
head:=1;
tail:=1;
dl[1]:=0;
fillchar(dist,sizeof(dist),0);
fillchar(visit,sizeof(visit),false);
for i:=0 to n+1 do
lj[i]:=nil;
visit[0]:=true;
dist[0]:=1;
while head<=tail do
begin
p:=con[dl[head]];
while p<>nil do
begin
if (p^.c>p^.f)and(dist[p^.t]<dist[dl[head]]*p^.w-res) then
begin
dist[p^.t]:=dist[dl[head]]*p^.w;
lj[p^.t]:=p;
if visit[p^.t]=false then
begin
inc(tail);
dl[tail]:=p^.t;
visit[p^.t]:=true;
end;
end;
p:=p^.next;
end;
visit[dl[head]]:=false;
dl[head]:=0;
inc(head);
end;
if dist[n+1]=0 then begin ans:=0; exit; end;
minf:=k-flow;
p:=lj[n+1];
while p<>nil do
begin
minf:=min(minf,p^.c-p^.f);
p:=lj[p^.rev^.t];
end;
p:=lj[n+1];
while p<>nil do
begin
p^.rev^.f:=p^.rev^.f-minf;
p^.f:=p^.f+minf;
p:=lj[p^.rev^.t];
end;
for i:=1 to minf do
ans:=ans*dist[n+1];
flow:=flow+minf;
end;
end;
begin
readln(n,k);
for i:=1 to n do
read(o1[i]);
for i:=1 to n do
read(o2[i]);
for i:=1 to n do
if o2[i]>0 then ins(0,i,o2[i],o1[i]);
for i:=1 to n do
begin
read(x);
if x=1 then ins(i,n+1,k+1,1);
end;
while true do
begin
read(x,y);
if (x=-1)and(y=-1) then break;
readln(w,z);
ins(x,y,z,w);
ins(y,x,z,w);
end;
spfa;
u:=ans;
v:=-1;
while u<1 do
begin
inc(v);
u:=u*10;
end;
writeln(ans:0:(v+5));
end.