您的位置:首页 > 其它

bzoj 1070 修车 费用流

2013-12-03 21:15 197 查看
对于这道题,我们看数据范围应该是费用流(起码我的第一反应是。。。)

然后仔细想想发现可做,那么就开始构图

对于第I个修理工,我们可以让他修好多辆车,那么假设一个人修了J辆车,

在他修他修的第K辆车的时候,会让后面的j-k辆车的每个人多等他修k车的时间

那么我们设每个人一共修了n辆车,他倒数第j个修的车的代价就是j*time(修这辆车的代价)

那么我们就对于每个人拆点,拆成N个点,代表他倒数第J个修的哪个车,然后求最小费用最大流就行了

数据范围开始看成60,60了,数组开的不合适,后来懒得改了。。。。

/**************************************************************
Problem: 1070
User: BLADEVIL
Language: Pascal
Result: Accepted
Time:556 ms
Memory:8532 kb
****************************************************************/

//By BLADEVIL
var
n, m                    :longint;
time                    :array[0..100,0..100] of longint;
pre, other, len, cost   :array[0..500000] of longint;
l                       :longint;
last                    :array[-10..5000] of longint;
tot                     :longint;
st, fin                 :longint;
que                     :array[0..100000] of longint;
dis, father             :array[-10..5000] of longint;
ans                     :longint;
flag                    :array[-10..5000] of boolean;

function min(a,b:longint):longint;
begin
if a>b then min:=b else min:=a;
end;

procedure connect(a,b,c,d:longint);
begin
inc(l);
pre[l]:=last[a];
last[a]:=l;
other[l]:=b;
len[l]:=c;
cost[l]:=d;
end;

procedure init;
var
i, j, k                 :longint;

begin
read(n,m); l:=1;
for i:=1 to m do
for j:=1 to n do read(time[j,i]);

st:=-1; fin:=-2;
tot:=m;
for i:=1 to m do
begin
connect(i,fin,1,0);
connect(fin,i,0,0);
end;
for i:=1 to n do
for j:=1 to m do
begin
inc(tot);
for k:=1 to m do
begin
connect(tot,k,1,j*time[i,k]);
connect(k,tot,0,-j*time[i,k]);
end;
end;
for i:=m+1 to tot do
begin
connect(st,i,1,0);
connect(i,st,0,0);
end;
end;

procedure spfa;
var
q, p, cur               :longint;
h, t                    :longint;
begin
filldword(dis,sizeof(dis) div 4,maxlongint div 10);
que[1]:=st;
dis[st]:=0;
h:=0; t:=1;
while t<>h do
begin
h:=h mod 100000+1;
cur:=que[h];
flag[cur]:=false;
q:=last[cur];
while q<>0 do
begin
p:=other[q];
if len[q]>0 then
begin
if dis[p]>dis[cur]+cost[q] then
begin
father[p]:=q;
dis[p]:=dis[cur]+cost[q];
if not flag[p] then
begin
t:=t mod 100000+1;
que[t]:=p;
flag[p]:=true;
end;
end;
end;
q:=pre[q];
end;
end;
end;

procedure update;
var
cur                     :longint;
low                     :longint;

begin
low:=maxlongint div 10;
cur:=fin;
while cur<>st do
begin
low:=min(low,len[father[cur]]);
inc(ans,cost[father[cur]]);
cur:=other[father[cur] xor 1];
end;
cur:=fin;
while cur<>st do
begin
dec(len[father[cur]],low);
inc(len[father[cur] xor 1],low);
cur:=other[father[cur] xor 1];
end;
end;

procedure main;
begin
ans:=0;
while true do
begin
spfa;
if dis[fin]=maxlongint div 10 then break;
update;
end;
writeln(ans/m:0:2);
end;

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