[费用流][BZOJ1070]修车
修车
题目描述
同一时刻有位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
输入
第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。
输出
最小平均等待时间,答案精确到小数点后2位。
样例输入
2 2
3 2
1 4
样例输出
1.50
提示
2<=M<=9,1<=N<=60 , 1<=T<=1000
又是一题看题解过的题...费用流难哇qaqq
对于每一个修车♂师傅,拆成N个点表示修N辆车
把车和所有的修车师傅拆成的N * M个点连边,记A[i, j]为第i个师傅修倒数第j辆车,流量为1(每辆车只能被修♂一次),费用为time[i , j] * k
关于费用:因为第j辆车在倒数第k个被修因此对全局产生的费用为time[i, j] * k (通俗的来说就是后面的人要排队啦w
S连每辆车,费用为0流量为1,每个师傅拆成的点连T,费用为0流量为1。
然后跑一遍MCMF结果除以k就好啦owo
代码:
1 #include<algorithm> 2 #include<cstdio> 3 #include<cstring> 4 5 const int Maxv = 1010, inf = 0x6ffffff, T = 1001; 6 int Next[Maxv], Head[Maxv], from[Maxv], tim[61][10], w[Maxv], v[Maxv], q[Maxv], d[Maxv], ans, cnt = 1, n, m; 7 bool inq[Maxv]; 8 struct edge{ 9 int from, to, next, c, v; 10 }e[100001]; 11 12 int read(){ 13 int x = 0, f = 1; 14 char c = getchar(); 15 while (c < '0' || c > '9') { 16 if (c == '-') { 17 f = -1; 18 } 19 c = getchar(); 20 } 21 while(c >= '0' && c <= '9') { 22 x = x * 10 + c - '0'; 23 c = getchar(); 24 } 25 return x * f; 26 } 27 28 void Add(int u, int v, int w, int c) { 29 cnt++; 30 e[cnt].next = Head[u]; 31 e[cnt].to = v; 32 e[cnt].from = u; 33 e[cnt].c = c; 34 e[cnt].v = w; 35 Head[u] = cnt; 36 } 37 38 void Add_Edge(int u, int v, int w, int c) { 39 Add(u, v, w, c); 40 Add(v, u, 0, -c); 41 } 42 43 bool spfa() 44 { 45 for (int i = 0; i <= T; i++) { 46 d[i] = inf; 47 } 48 int t = 0, w = 1; 49 d[0] = 0; 50 inq[0] = true; 51 q[0] = 0; 52 while(t != w) { 53 int now = q[t]; 54 t++; 55 if(t == T) { 56 t = 0; 57 } 58 for (int i = Head[now]; i; i = e[i].next) { 59 if (e[i].v && d[e[i].to] > d[now] + e[i].c) { 60 d[e[i].to] = d[now] + e[i].c; 61 from[e[i].to] = i; 62 if (!inq[e[i].to]) { 63 inq[e[i].to] = true; 64 q[w++] = e[i].to; 65 if(w == T) { 66 w = 0; 67 } 68 } 69 } 70 } 71 inq[now] = false; 72 } 73 if (d[T] == inf) { 74 return false; 75 } 76 return true; 77 } 78 79 void mcf() 80 { 81 int x = inf; 82 for (int i = from[T]; i; i = from[e[i].from]) { 83 x = std::min(x, e[i].v); 84 } 85 for (int i = from[T]; i; i = from[e[i].from]) { 86 e[i].v -= x; 87 e[i ^ 1].v += x; 88 ans += e[i].c * x; 89 } 90 } 91 92 int main(){ 93 n = read(); 94 m = read(); 95 for (int i = 1; i <= m; i++) { 96 for (int j = 1; j <= n; j++) { 97 tim[i][j] = read(); 98 } 99 } 100 for (int i = 1; i <= n * m; i++) { 101 Add_Edge(0, i, 1, 0); 102 } 103 for (int i = n * m + 1; i <= n * m + m; i++) { 104 Add_Edge(i, T, 1, 0); 105 } 106 for (int i = 1; i <= n; i++) { 107 for (int j = 1; j <= m; j++) { 108 for (int k = 1; k <= m; k++) { 109 Add_Edge((i - 1) * m + j, n * m + k, 1, tim[k][i] * j); 110 } 111 } 112 } 113 while (spfa()) { 114 mcf(); 115 } 116 printf("%.2lf", (double)ans / m); 117 return 0; 118 }