SCOI2007修车
这样也行?这构图把我惊呆了:
把每个工人拆成N个点。记为A[i,j]表示第i个工人修倒数第j辆车。
每个车跟所有N*M个工人拆出的点连边。流量为1,费用为time[i,j]*k。
源和每辆车连边,N*M个点和汇连边,流量都为1,费用同为0。
为什么这么构图呢?
考虑第i个工人,他修第j辆车只对后面要修的车有影响,而前面修过的车已经对当前没有影响了。
而这个影响就是后面每个将要修理的车都多等待了time的时间
其他边流量都为1是显然的,每辆车修一次,每个工人一个时段只能修理一辆车。
ps:bzoj上什么错误都是WA啊……
代码:
1 uses math; 2 const inf=maxlongint; 3 type node=record 4 from,go,next,v,c:longint; 5 end; 6 var i,j,k,n,m,ans,s,t,cnt:longint; 7 pre,d,first,q:array[0..10000] of longint; 8 e:array[0..100000] of node; 9 time:array[0..100,0..100] of longint; 10 procedure ins(u,v,w,c:longint); 11 begin 12 inc(cnt); 13 e[cnt].go:=v;e[cnt].from:=u; 14 e[cnt].v:=w;e[cnt].c:=c; 15 e[cnt].next:=first[u];first[u]:=cnt; 16 end; 17 procedure insert(u,v,w,c:longint); 18 begin 19 ins(u,v,w,c);ins(v,u,0,-c); 20 end; 21 function spfa:boolean; 22 var head,tail,i,x,y:longint; 23 v:array[0..10000] of boolean; 24 begin 25 head:=0;tail:=1;q[1]:=s;d[s]:=0; 26 for i:=1 to t do d[i]:=inf; 27 fillchar(v,sizeof(v),false); 28 v[s]:=true; 29 while head<tail do 30 begin 31 inc(head); 32 x:=q[head]; 33 i:=first[x]; 34 v[x]:=false; 35 while i<>0 do 36 begin 37 y:=e[i].go; 38 if (e[i].v<>0) and (d[x]+e[i].c<d[y]) then 39 begin 40 pre[y]:=i; 41 d[y]:=d[x]+e[i].c; 42 if not(v[y]) then 43 begin 44 inc(tail); 45 q[tail]:=y; 46 v[y]:=true; 47 end; 48 end; 49 i:=e[i].next; 50 end; 51 end; 52 exit(d[t]<>inf); 53 end; 54 procedure mcf; 55 var i,x:longint; 56 begin 57 i:=pre[t]; x:=inf; 58 while i<>0 do 59 begin 60 x:=min(x,e[i].v); 61 i:=pre[e[i].from]; 62 end; 63 i:=pre[t]; 64 while i<>0 do 65 begin 66 dec(e[i].v,x); 67 inc(e[i xor 1].v,x); 68 i:=pre[e[i].from]; 69 end; 70 inc(ans,x*d[t]); 71 end; 72 73 procedure init; 74 begin 75 cnt:=1; 76 readln(m,n); 77 for i:=1 to n do 78 begin 79 for j:=1 to m do read(time[i,j]); 80 readln; 81 end; 82 end; 83 procedure main; 84 begin 85 s:=0;t:=n*m+n+2; 86 for i:=1 to n do insert(s,i,1,0); 87 for i:=n+1 to n*m+n+1 do insert(i,t,1,0); 88 for i:=1 to m do 89 for j:=1 to n do 90 for k:=1 to n do 91 insert(k,i*n+j,1,time[k,i]*j); 92 ans:=0; 93 while spfa do mcf; 94 writeln(ans/n:0:2); 95 end; 96 begin 97 init; 98 main; 99 end.