平均时间最短即总时间最短
首先不难想到,将每个工作人员拆成n个点
然后,我就卡住了,
的确,正向建图确实很难,因为我们不好表示在修第i个车之前,前面用了多少时间
于是我们应该逆向想一想,将这辆车作为某个工作人员倒数第k个修的车会对之后的时间做怎样的影响
显然,每个工作人员修车是相对独立的
也就是说,工作人员i倒数第k个修车j时对后续他修的车时间影响总和是time[i,j]*k
于是,每个工作人员拆成的n个点意义就明确了;
图就好建了;
当然,这是一个二分图,可以KM,可以最小费用最大流,
作为不会KM的弱渣,我就用最小费用最大流吧
1 const inf=100000007; 2 type node=record 3 next,flow,cost,from,point:longint; 4 end; 5 var edge:array[0..400010] of node; 6 q:array[0..400010] of longint; 7 a:array[0..70,0..70] of longint; 8 pre,d,p:array[0..800] of longint; 9 v:array[0..800] of boolean; 10 ans,len,t,n,m,x,i,j,k:longint; 11 12 procedure add(x,y,f,w:longint); 13 begin 14 inc(len); 15 edge[len].from:=x; 16 edge[len].point:=y; 17 edge[len].flow:=f; 18 edge[len].cost:=w; 19 edge[len].next:=p[x]; 20 p[x]:=len; 21 end; 22 23 function spfa:boolean; 24 var f,r,x,y,i:longint; 25 begin 26 for i:=1 to t do 27 d[i]:=inf; 28 d[0]:=0; 29 fillchar(v,sizeof(v),false); 30 v[0]:=true; 31 f:=1; 32 r:=1; 33 q[1]:=0; 34 while f<=r do 35 begin 36 x:=q[f]; 37 v[x]:=false; 38 i:=p[x]; 39 while i<>-1 do 40 begin 41 y:=edge[i].point; 42 if edge[i].flow>0 then 43 begin 44 if d[y]>d[x]+edge[i].cost then 45 begin 46 d[y]:=d[x]+edge[i].cost; 47 pre[y]:=i; 48 if not v[y] then 49 begin 50 v[y]:=true; 51 inc(r); 52 q[r]:=y; 53 end; 54 end; 55 end; 56 i:=edge[i].next; 57 end; 58 inc(f); 59 end; 60 if d[t]>=inf then exit(false) else exit(true); 61 end; 62 63 procedure mincost; 64 var i,j:longint; 65 begin 66 while spfa do 67 begin 68 i:=t; 69 while i<>0 do 70 begin 71 j:=pre[i]; 72 dec(edge[j].flow); 73 inc(edge[j xor 1].flow); 74 i:=edge[j].from; 75 end; 76 ans:=ans+d[t]; 77 end; 78 end; 79 80 begin 81 readln(m,n); 82 len:=-1; 83 fillchar(p,sizeof(p),255); 84 for i:=1 to n do 85 begin 86 for j:=1 to m do 87 read(a[i,j]); 88 readln; 89 end; 90 for i:=1 to n do 91 begin 92 add(0,m*n+i,1,0); 93 add(m*n+i,0,0,0); 94 end; 95 t:=m*n+n+1; 96 for i:=1 to m do 97 begin 98 for j:=1 to n do 99 begin 100 add((j-1)*m+i,t,1,0); 101 add(t,(j-1)*m+i,0,0); 102 end; 103 for j:=1 to n do 104 for k:=1 to n do 105 begin 106 x:=a[j,i]*(n-k+1); 107 add(j+m*n,i+(k-1)*m,1,x); 108 add(i+(k-1)*m,j+m*n,0,-x); 109 end; 110 end; 111 mincost; 112 writeln(ans/n:0:2); 113 end.