平均时间最短即总时间最短

首先不难想到,将每个工作人员拆成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.
View Code

 

posted on 2014-04-12 23:16  acphile  阅读(115)  评论(0编辑  收藏  举报