bzoj 1070修车
1070: [SCOI2007]修车
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 3865 Solved: 1581
[Submit][Status][Discuss]
Description
同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
Input
第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
Output
最小平均等待时间,答案精确到小数点后2位。
Sample Input
2 2
3 2
1 4
3 2
1 4
Sample Output
1.50
HINT
数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)
最小费用最大流
时间的先后不好维护怎么办,讲工人拆成n个点,每个点表示第几个修当前这辆车。考虑第i个工人,他修第j辆车只对后面要修的车有影响,而前面修过的车已经对当前没有影响了
所以只需要将费用乘以k。然后每辆车向每个工人的每个点连费用不同的边,就可以轻松解决时间先后关系的问题。
方法:时间先后对费用有影响,将时间拆出来,分别考虑,讨论当前次序的费用,可以解决时间或次序的先后问题
注意:不要把n,m读反
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 1020 #define maxm 100020 #define inf 0x3f3f3f3f struct node{ int to,next,f,ct,from; }e[maxm * 2]; int head[maxn],cnt = 1,maxflow,mincost,dis[maxn],src,sink; int q[maxn * 10],hh,tt,inq[maxn],prev[maxn]; int n,m; int _time[100][100]; double ans; inline void adde(int x,int y,int c,int ct){ e[++cnt].to = y; e[cnt].from = x; e[cnt].next = head[x]; e[cnt].f = c; e[cnt].ct = ct; head[x] = cnt; e[++cnt].to = x; e[cnt].from = y; e[cnt].next = head[y]; e[cnt].f = 0; e[cnt].ct = -ct; head[y] = cnt; } inline bool spfa(){ memset(dis,0x3f,sizeof(dis)); tt = hh = 0; q[tt++] = src; dis[src] = 0; inq[src] = 1; while ( hh < tt ){ int now = q[hh++]; inq[now] = 0; for (int i = head[now] ; i ; i = e[i].next){ if ( e[i].f && dis[e[i].to] > dis[now] + e[i].ct ){ dis[e[i].to] = dis[now] + e[i].ct; prev[e[i].to] = i; if ( !inq[e[i].to] ) q[tt++] = e[i].to , inq[e[i].to] = 1; } } } return dis[sink] < inf; } int dfs(){ int delta = inf , x = sink; while ( x != src ){ delta = min(delta,e[prev[x]].f); x = e[prev[x]].from; } x = sink; while ( x != src ){ e[prev[x]].f -= delta; e[prev[x] ^ 1].f += delta; x = e[prev[x]].from; } return delta; } void init(){ for (int i = 1 ; i <= n ; i++) adde(i,sink,1,0); for (int i = 1 ; i <= m ; i++) for (int j = 1 ; j <= n ; j++){ adde(src,n + (i - 1) * n + j,1,0); } for (int i = 1 ; i <= n ; i++){ for (int j = 1 ; j <= m ; j++){ for (int k = 1 ; k <= n ; k++){ adde(n + (j - 1) * n + k,i,1,_time[j][i] * (n - k + 1)); } } } } int main(){ scanf("%d %d",&m,&n); src = n * m + n + 1 , sink = src + 1; for (int i = 1 ; i <= n ; i++){ for (int j = 1 ; j <= m ; j++){ scanf("%d",&_time[j][i]); } } init(); while ( spfa() ){ mincost += dfs() * dis[sink]; } ans = (double)mincost/(double)n; printf("%.2lf\n",ans); return 0; }