bzoj 1070[SCOI2007]修车 - 费用流
1070: [SCOI2007]修车
Time Limit: 1 Sec Memory Limit: 128 MBDescription
同一时刻有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)
对维修工拆点, 第k个维修工表示这辆车是他修的倒数k辆
对于 第 j 辆车连向第i个维修工的第k个节点的权值就是 k * a[i][j], 因为在他之后修的车都会加上等待的时间。
根据网络流的性质,他会优先跑小的边
所以跑费用流就是总的等待时间
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #define LL long long 7 8 using namespace std; 9 10 queue<int> q; 11 int cnt = 0; 12 const int MAXN = 1e3; 13 int ti; 14 int dis[MAXN]; 15 int flag[MAXN]; 16 int head[MAXN]; 17 int N, M; 18 int V; 19 int S, T; 20 int pre[MAXN]; 21 int e[MAXN]; 22 struct edge { 23 int v; 24 int next; 25 int w; 26 int cost; 27 } g[600 * 600 * 10]; 28 29 double ans = 0; 30 void addedge(int u, int v, int w, double cost) 31 { 32 g[cnt].v = v; 33 g[cnt].w = w; 34 g[cnt].cost = cost; 35 g[cnt].next = head[u]; 36 head[u] = cnt++; 37 } 38 inline LL read() 39 { 40 LL x = 0, w = 1; char ch = 0; 41 while(ch < '0' || ch > '9') { 42 if(ch == '-') { 43 w = -1; 44 } 45 ch = getchar(); 46 } 47 while(ch >= '0' && ch <= '9') { 48 x = x * 10 + ch - '0'; 49 ch = getchar(); 50 } 51 return x * w; 52 } 53 54 bool SPFA() 55 { 56 while(!q.empty()) { 57 q.pop(); 58 } 59 memset(pre, 0, sizeof pre); 60 memset(flag, 0, sizeof flag); 61 memset(dis, 0x3f, sizeof dis); 62 dis[0] = 0; 63 q.push(S); 64 while(!q.empty()) { 65 int t = q.front(); 66 flag[t] = 0; 67 q.pop(); 68 for(int j = head[t]; j != -1; j = g[j].next) { 69 int to = g[j].v; 70 if(dis[to] > dis[t] + g[j].cost && g[j].w > 0) { 71 dis[to] = dis[t] + g[j].cost; 72 // cout<<dis[to]<<endl; 73 pre[to] = t; 74 /*if(dis[to] < 0 && to == 0) { 75 for(int j = t; j ; j = pre[j]) { 76 cout<<j<<" "<<dis[j]<<endl; 77 } 78 cout<<endl; 79 exit(0); 80 }*/ 81 e[to] = j; 82 if(!flag[to]) { 83 flag[to] = 1; 84 q.push(to); 85 } 86 } 87 } 88 } 89 if(!pre[T]) { 90 return false; 91 } 92 ans += dis[T]; 93 int minflow = 1e9; 94 for(int j = T; j; j = pre[j]) { 95 //cout<<j<<" "; 96 minflow = min(minflow, g[e[j]].w); 97 } 98 //cout<<endl; 99 //cout<<dis[T]<<" "<<minflow<<endl<<endl; 100 for(int j = T; j; j = pre[j]) { 101 g[e[j]].w -= minflow; 102 g[e[j] ^ 1].w += minflow; 103 } 104 return true; 105 } 106 107 int main() 108 { 109 memset(head, -1, sizeof head); 110 M = read(), N = read(); 111 V = M * N; 112 S = 0, T = V + N + 1; 113 for(int i = 1; i <= N; i++) { 114 addedge(S, V + i, 1, 0); 115 addedge(V + i,S, 0, 0); 116 for(int j = 1; j <= M; j++) { 117 scanf("%d", &ti); 118 for(int t = 1; t <= N; t++) { 119 addedge((t - 1) * M + j, V + i, 0, -1 * ti * t); 120 addedge(V + i, (t - 1) * M + j, 1, 1 * ti * t); 121 } 122 } 123 } 124 for(int i = 1; i <= M * N; i++) { 125 addedge(i, T, 1, 0); 126 addedge(T, i, 0, 0); 127 } 128 while(SPFA()) { 129 } 130 printf("%.2lf\n", ans / N); 131 return 0; 132 } 133 134 /* 135 2 2 136 3 2 137 1 4 138 139 */