首先,源点向每一个车主连(1,0)的边,然后把每一个工人拆成n个点,第i个点表示修倒数第i辆车,那么这辆车对答案的代价就是time*i(time表示这辆车的时间,i表示倒数第i辆),就是说每一个车主向nm个工人的点连(1,time*i)的边。最后,每一个工人的点向汇点连(1,0)的边即可。

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 1005
4 #define oo 0x3f3f3f3f
5 struct ji{
6 int nex,to,len,cost;
7 }edge[N*70];
8 queue<int>q;
9 int E,n,m,t,head[N],from[N],d[N],vis[N];
10 void add(int x,int y,int z,int w){
11 edge[E].nex=head[x];
12 edge[E].to=y;
13 edge[E].len=z;
14 edge[E].cost=w;
15 head[x]=E++;
16 if (E&1)add(y,x,0,-w);
17 }
18 bool spfa(){
19 memset(vis,0,sizeof(vis));
20 memset(d,oo,sizeof(d));
21 d[0]=0;
22 q.push(0);
23 while (!q.empty()){
24 int k=q.front();
25 q.pop();
26 vis[k]=0;
27 for(int i=head[k];i!=-1;i=edge[i].nex){
28 int v=edge[i].to;
29 if ((edge[i].len)&&(d[v]>d[k]+edge[i].cost)){
30 d[v]=d[k]+edge[i].cost;
31 from[v]=i;
32 if (!vis[v]){
33 vis[v]=1;
34 q.push(v);
35 }
36 }
37 }
38 }
39 return d[t]<oo;
40 }
41 int dinic(){
42 int ans=0;
43 while (spfa()){
44 ans+=d[t];
45 for(int i=t;i;i=edge[from[i]^1].to){
46 edge[from[i]].len--;
47 edge[from[i]^1].len++;
48 }
49 }
50 return ans;
51 }
52 int main(){
53 scanf("%d%d",&m,&n);
54 memset(head,-1,sizeof(head));
55 for(int i=1;i<=n;i++)add(0,i,1,0);
56 for(int i=1;i<=n;i++)
57 for(int j=1;j<=m;j++){
58 scanf("%d",&t);
59 for(int k=1;k<=n;k++)add(i,j*n+k,1,t*k);
60 }
61 for(int i=1;i<=m;i++)
62 for(int j=1;j<=n;j++)add(i*n+j,n*m+n+1,1,0);
63 t=n*m+n+1;
64 printf("%.2f",dinic()*1.0/n);
65 }
