您的位置:首页 > 其它

1070: [SCOI2007]修车 - BZOJ

2014-04-23 17:57 363 查看
Description

同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
Input

第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
Output

最小平均等待时间,答案精确到小数点后2位。
Sample Input
2 2
3 2
1 4
Sample Output
1.50

HINT

数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)

费用流建图,把m个人每个人拆成n个点,表示的是第m个人倒数第i个修这个车,那么费用就是i*时间

没想到zkw费用流模板打错了

在dfs过程里

我是这么写的

function dfs(x,flow:longint):longint;
var
i,d,min:longint;
begin
flag[x]:=time;
if x=t then
begin
inc(ans,flow*dis[t]);
exit(flow);
end;
i:=first[x];
dfs:=0;
while i<>0 do
begin
d:=dis[x]+w[i]-dis[last[i]];
min:=flow;
if min>liu[i] then min:=liu[i];
if (liu[i]>0) and (d<f[last[i]]) then f[last[i]]:=d;
if (d=0) and (flag[last[i]]<>time) and (min>0) then
begin
d:=dfs(last[i],min);
dec(flow,d);
inc(dfs,d);
inc(liu[i xor 1],d);
dec(liu[i],d);
end;
if flow=0 then break;
i:=next[i];
end;
end;


但是应该这么写

function dfs(x,flow:longint):longint;
var
i,d,min:longint;
begin
if x=t then
begin
inc(ans,flow*dis[t]);
exit(flow);
end;
i:=first[x];
flag[x]:=time;
dfs:=0;
while i<>0 do
begin
d:=dis[x]+w[i]-dis[last[i]];
min:=flow;
if min>liu[i] then min:=liu[i];
if (liu[i]>0) and (d<f[last[i]]) then f[last[i]]:=d;
if (d=0) and (flag[last[i]]<>time) and (min>0) then
begin
d:=dfs(last[i],min);
dec(flow,d);
inc(dfs,d);
inc(liu[i xor 1],d);
dec(liu[i],d);
end;
if flow=0 then break;
i:=next[i];
end;
end;


应该先判断是否走到了汇点,再做标记,如果不这样的话,就无法多路增广了,即只能到达汇点一次,然后他会立即增加dis,这个时候dis就是错的了(因为较小的那个dis还没有增广完全)

对于其他的点,都是增广到不能再增广,所以没有问题,只要访问一次就行了(应该是这样的吧)

写了几遍了,连这个都没有发现,唉~~~~

const
maxn=62;
maxm=10;
inf=100000000;
var
n,m,tot,s,t,ans,time:longint;
first,f,dis,flag:array[0..maxn*maxm]of longint;
last,next,w,liu:array[0..maxn*maxn*maxm*maxm]of longint;

procedure insert(x,y,f,ww:longint);
begin
inc(tot);
last[tot]:=y;
next[tot]:=first[x];
first[x]:=tot;
w[tot]:=ww;
liu[tot]:=f;
end;

procedure init;
var
i,j,k,x:longint;
begin
read(m,n);
tot:=1;
s:=0;
t:=n*m+n+1;
for i:=1 to n do
for j:=1 to m do
begin
read(x);
for k:=1 to n do
begin
insert((j-1)*n+k,n*m+i,1,x*k);
insert(n*m+i,(j-1)*n+k,0,-x*k);
end;
end;
for i:=1 to n*m do
begin
insert(s,i,1,0);
insert(i,s,0,0);
end;
for i:=1 to n do
begin
insert(n*m+i,t,1,0);
insert(t,n*m+i,0,0);
end;
end;

function dfs(x,flow:longint):longint;
var
i,d,min:longint;
begin
if x=t then
begin
inc(ans,flow*dis[t]);
exit(flow);
end;
i:=first[x];
flag[x]:=time;
dfs:=0;
while i<>0 do
begin
d:=dis[x]+w[i]-dis[last[i]];
min:=flow;
if min>liu[i] then min:=liu[i];
if (liu[i]>0) and (d<f[last[i]]) then f[last[i]]:=d;
if (d=0) and (flag[last[i]]<>time) and (min>0) then
begin
d:=dfs(last[i],min);
dec(flow,d);
inc(dfs,d);
inc(liu[i xor 1],d);
dec(liu[i],d);
end;
if flow=0 then break;
i:=next[i];
end;
end;

procedure work;
var
del,i:longint;
begin
while true do
begin
for i:=s to t do
f[i]:=inf;
inc(time);
dfs(s,inf);
del:=inf;
for i:=s to t do
if (flag[i]<>time) and (f[i]<del) then del:=f[i];
if del=inf then break;
for i:=s to t do
if flag[i]<>time then inc(dis[i],del);
end;
writeln(ans/n:0:2);
end;

begin
init;
work;
end.


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: