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.            
View Code
原文地址:https://www.cnblogs.com/zyfzyf/p/3801327.html