题目描述
同一时刻有位车主带着他们的爱车来到了汽车维修中心。
维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。
现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。
说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
输入
第一行有两个m,n,表示技术人员数与顾客数。
接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
输出
样例输入
2 2
3 2
1 4
样例输出
1.50
提示
2<=M<=9,1<=N<=60 , 1<=T<=1000
费用流
建一个源点S与汇点T,
把S向每辆车连容量为1,费用为0的边,表示每辆车只被修一次
把每个技术人员拆n个点,第j个技术人员拆的第i个点表示第j个人倒数第i个修车
把拆出来的每个点向T连容量为1,费用为0的边
每辆车向每个点连边,流量1,费用是(之后的车的数量+1)*修它的时间。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int inq[100000],d[100000],h[100000],q[200000],from[100000],head,tail,k=1,INF=999999999,ans=0,used[100000]; int a[61][10]; struct data{ int to,cap,cost,next; }g[1000000]; void add(int from,int to,int cap,int cost) { g[++k].next=h[from];h[from]=k;g[k].to=to;g[k].cap=cap;g[k].cost=cost; g[++k].next=h[to];h[to]=k;g[k].to=from;g[k].cap=0;g[k].cost=-cost; } bool spfa(int s,int t) { head=tail=100000; memset(d,127/3,sizeof(d));INF=d[0]; memset(inq,0,sizeof(inq)); q[tail++]=t;d[t]=0;inq[t]=1; while(head<=tail) { int u=q[head++];inq[u]=0; for(int i=h[u];i;i=g[i].next) { if(g[i^1].cap&&d[u]+g[i^1].cost<d[g[i].to]) { d[g[i].to]=d[u]+g[i^1].cost; if(!inq[g[i].to]) { if(d[g[i].to]<d[q[head]])q[--head]=g[i].to; else q[tail++]=g[i].to;inq[g[i].to]=1; } } } } return d[s]!=INF; } int dfs(int u,int t,int f) { used[u]=1; if(u==t)return f; int _used=0,w; for(int i=h[u];i;i=g[i].next) { if(!used[g[i].to]&&g[i].cap&&d[u]-g[i].cost==d[g[i].to]) { w=dfs(g[i].to,t,min(g[i].cap,f-_used)); if(w) { _used+=w;g[i].cap-=w;g[i^1].cap+=w;ans+=w*g[i].cost; if(_used==f)return f; } } } return _used; } void PD(int s,int t) { while(spfa(s,t)) { used[t]=1; while(used[t]) { memset(used,0,sizeof(used)); dfs(s,t,INF); } } } int main() { int m,n;scanf("%d%d",&m,&n); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&a[i][j]); } int S=n+n*m+1,T=n+n*m+2; for(int i=n+1;i<=n*m+n;i++)add(i,T,1,0); for(int i=1;i<=n;i++)add(S,i,1,0); for(int i=1;i<=n;i++)//第i个人 for(int j=1;j<=m;j++)//修理第j辆车 for(int k=1;k<=n;k++)//倒数第k个修 { add(i,j*n+k,1,a[i][j]*k); } PD(S,T); printf("%.2f",(double)ans/n);return 0; }