[BZOJ1070][SCOI2007]修车
1070: [SCOI2007]修车
Time Limit: 1 Sec Memory Limit: 128 MB Submit: 6007 Solved: 2559 [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$个点,每个点在连边时费用对应乘上相应的倍数,因为如果一个维修师傅修多个车的话等待时间需要乘上一定倍数。然后跑最小费用最大流
#include <cstdio> inline int readint(){ int f = 1, n = 0; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch <= '9' && ch >= '0'){ n = (n << 1) + (n << 3) + ch - '0'; ch = getchar(); } return f * n; } const int maxn = 100, maxm = 15, INF = 0x3f3f3f3f; struct Edge{ int to, cap, cost, next; Edge(){} Edge(int _t, int _w, int _c, int _n): to(_t), cap(_w), cost(_c), next(_n){} }e[maxn + maxn * maxn * maxm + maxn * maxm << 1]; int fir[maxn + maxn * maxm] = {0}, cnt = 1; inline void ins(int u, int v, int w, int c){ e[++cnt] = Edge(v, w, c, fir[u]); fir[u] = cnt; e[++cnt] = Edge(u, 0, -c, fir[v]); fir[v] = cnt; } int sour, sink; bool inq[maxn + maxn * maxm] = {false}; int dis[maxn + maxn * maxm]; int q[maxn + maxn * maxm], head, tail; int pre[maxn + maxn * maxm]; bool SPFA(){ for(int i = sour; i <= sink; i++){ dis[i] = INF; inq[i] = false; pre[i] = 0; } head = tail = 0; dis[sour] = 0; inq[sour] = true; q[tail++] = sour; int u, v; while(head != tail){ u = q[head++]; if(head == 1600) head = 0; inq[u] = false; for(int i = fir[u]; i; i = e[i].next){ v = e[i].to; if(e[i].cap && dis[v] > dis[u] + e[i].cost){ dis[v] = dis[u] + e[i].cost; pre[v] = i; if(!inq[v]){ inq[v] = true; q[tail++] = v; if(tail == 1600) tail = 0; } } } } return dis[sink] != INF; } int MCMF(){ int flow, cost = 0; while(SPFA()){ flow = INF; for(int i = pre[sink]; i; i = pre[e[i ^ 1].to]) if(e[i].cap < flow) flow = e[i].cap; for(int i = pre[sink]; i; i = pre[e[i ^ 1].to]){ e[i].cap -= flow; e[i ^ 1].cap += flow; } cost += flow * dis[sink]; } return cost; } int main(){ int m, n; m = readint(); n = readint(); sour = 0; sink = n + n * m + 1; for(int i = 1; i <= n; i++) ins(sour, i, 1, 0); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){ int t = readint(); for(int k = 1; k <= n; k++) ins(i, j * n + k, 1, k * t); } for(int i = 1; i <= m; i++) for(int j = 1; j <= n; j++) ins(i * n + j, sink, 1, 0); printf("%.2lf\n", MCMF() * 1.0 / n); return 0; }