同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。
说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
输入
第一行有两个数M,N,表示技术人员数与顾客数。
接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
输出
最小平均等待时间,答案精确到小数点后2位。
样例
repair.in
2 2
3 2
1 4
repair.out
1.50
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
网上的题解好多都特别粗略,我走了好多弯路。
所以决定写详细一点:把每个修理工变为N个点,表示倒数第1~N个修理的车,为啥是倒数呢?因为不知道一个人究竟修了几辆车,又因为倒数第一的总比倒数第二的更优,费用流会优先倒数第一的,再倒数第二的,所以用倒数的可以很好地解决。多么的巧妙!!!然后是这样建图的:S向每个人的每个倒数第几维修的点连一条流量为1,费用为0的边;接着再新建N个点,代表N辆车,每个人的每个倒数第几维修的点向其连一条流量为1,费用为(当前是倒数第i个的i)*(第j个人修第k辆车的时间);最后由N辆车的向T连容量为1,费用为0的边。
1 #include2 #include 3 #include 4 #include 5 using namespace std; 6 const int INF=1000000000; 7 const int maxn=1010,maxm=400010; 8 int cnt=1,fir[maxn],nxt[maxm],to[maxm]; 9 int cap[maxm],val[maxm],dis[maxn],path[maxn];10 11 void add(int a,int b,int c,int v){12 nxt[++cnt]=fir[a];to[cnt]=b;13 cap[cnt]=c;val[cnt]=v;fir[a]=cnt;14 }15 void addedge(int a,int b,int c,int v){16 add(a,b,c,v);17 add(b,a,0,-v);18 }19 20 int S,T;21 int vis[maxn];22 int Spfa(){23 deque q;24 memset(dis,127,sizeof(dis));25 memset(vis,0,sizeof(vis));26 q.push_front(S);27 dis[S]=0;vis[S]=1;28 while(!q.empty()){29 int x=q.front();q.pop_front();vis[x]=0;30 for(int i=fir[x];i;i=nxt[i])31 if(cap[i]&&dis[x]+val[i]