【BZOJ1070】修车(费用流)
题意:同一时刻有N位车主带着他们的爱车来到了汽车维修中心。
维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。
现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。
说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
题意:RYZ作业
费用流经典模型之一
对于一次修车我们有三个属性,车的编号,人的编号,以及它是这个人倒数第几个修的车
为什么不是正数第几个?因为不知道每个人各自要修多少辆,这样就无法统计它让后面的车主等待的时间
而对于倒数第K修的车,它让后面以及当前的的车主多等待了a[i,j]*k的时间
将人裂点,(i,j)表示这是第i个人修的倒数第j辆车
源点连车,容量为1,费用为0
车连人裂的点,容量为1,费用为a[i,j]*k
人裂的点连汇点,容量为1,费用为0
1 var head,vet,next,len1,len2,dis,fan:array[1..200000]of longint; 2 inq:array[1..200000]of boolean; 3 pre:array[1..200000,1..2]of longint; 4 q:array[0..3000]of longint; 5 a,num:array[1..60,1..60]of longint; 6 n,m,i,j,k,tot,src,source,s:longint; 7 ans:double; 8 9 function min(x,y:longint):longint; 10 begin 11 if x<y then exit(x); 12 exit(y); 13 end; 14 15 procedure add(a,b,c,d:longint); 16 begin 17 //writeln(a,' ',b,' ',c,' ',d); 18 inc(tot); 19 next[tot]:=head[a]; 20 vet[tot]:=b; 21 len1[tot]:=c; 22 len2[tot]:=d; 23 head[a]:=tot; 24 25 inc(tot); 26 next[tot]:=head[b]; 27 vet[tot]:=a; 28 len1[tot]:=0; 29 len2[tot]:=-d; 30 head[b]:=tot; 31 end; 32 33 34 function spfa:boolean; 35 var u,e,v,i,t,w:longint; 36 begin 37 for i:=1 to s do 38 begin 39 dis[i]:=maxlongint>>1; 40 inq[i]:=false; 41 end; 42 t:=0; w:=1; q[1]:=source; dis[source]:=0; inq[source]:=true; 43 while t<w do 44 begin 45 inc(t); u:=q[t mod 3000]; 46 inq[u]:=false; 47 e:=head[u]; 48 while e<>0 do 49 begin 50 v:=vet[e]; 51 if (len1[e]>0)and(dis[u]+len2[e]<dis[v]) then 52 begin 53 pre[v,1]:=u; 54 pre[v,2]:=e; 55 dis[v]:=dis[u]+len2[e]; 56 if not inq[v] then 57 begin 58 inc(w); q[w mod 3000]:=v; inq[v]:=true; 59 end; 60 end; 61 e:=next[e]; 62 end; 63 end; 64 if dis[src]=maxlongint>>1 then exit(false); 65 exit(true); 66 end; 67 68 procedure mcf; 69 var k,e,t:longint; 70 begin 71 k:=src; t:=maxlongint; 72 while k<>source do 73 begin 74 t:=min(t,len1[pre[k,2]]); 75 k:=pre[k,1]; 76 end; 77 k:=src; 78 while k<>source do 79 begin 80 e:=pre[k,2]; 81 len1[e]:=len1[e]-t; 82 len1[fan[e]]:=len1[fan[e]]+t; 83 ans:=ans+t*len2[e]; 84 k:=pre[k,1]; 85 end; 86 end; 87 88 begin 89 assign(input,'bzoj1070.in'); reset(input); 90 assign(output,'bzoj1070.out'); rewrite(output); 91 readln(m,n); 92 for i:=1 to 200000 do 93 if i and 1=1 then fan[i]:=i+1 94 else fan[i]:=i-1; 95 for i:=1 to n do 96 for j:=1 to m do read(a[i,j]); 97 s:=n; 98 for i:=1 to m do 99 for j:=1 to n do 100 begin 101 inc(s); num[i,j]:=s; 102 end; 103 inc(s); source:=s; 104 inc(s); src:=s; 105 for i:=1 to n do add(source,i,1,0); 106 for i:=1 to n do 107 for j:=1 to m do 108 for k:=1 to n do add(i,num[j,k],1,a[i,j]*k); 109 for i:=1 to m do 110 for j:=1 to n do add(num[i,j],src,1,0); 111 while spfa do mcf; 112 writeln(ans/n:0:2); 113 close(input); 114 close(output); 115 end.
null