bzoj 1070 修车 费用流
对于这道题,我们看数据范围应该是费用流(起码我的第一反应是。。。)
然后仔细想想发现可做,那么就开始构图
对于第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.