洛谷P2053 修车
修车修到jiry报废(滑稽)
题意:m个人修n个车,同时开始。
每辆车只能给一个人修。每个人修每辆车的用时都不同。
问怎样安排能使每辆车的等待时间总和最少。
解:
一直想的是用以流量表示一个人,没想到是一流量表示一辆车......
答案统计也想错了...应该是统计每辆车修的时候对它以及它后面车的贡献。
比如当前这辆车的后面还有k辆,那么时间就要乘k + 1
每辆车可以给每个人修,后面可以安排任意辆车。据此拆点,把每个人拆成n个。
源点向车连边,车向每个人的后面有几辆车(一共m * n个点)连边,然后连到汇点。
跑最小费用最大流即可。
1 #include <cstdio> 2 #include <algorithm> 3 #include <queue> 4 #include <cstring> 5 6 const int N = 710, M = 1000010, INF = 0x3f3f3f3f; 7 8 struct Edge { 9 int nex, v, c, len; 10 }edge[M << 1]; int top = 1; 11 12 int e[N], d[N], vis[N], pre[N], flow[N]; 13 std::queue<int> Q; 14 int G[70][13]; 15 16 inline void add(int x, int y, int z, int w) { 17 top++; 18 edge[top].v = y; 19 edge[top].c = z; 20 edge[top].len = w; 21 edge[top].nex = e[x]; 22 e[x] = top; 23 24 top++; 25 edge[top].v = x; 26 edge[top].c = 0; 27 edge[top].len = -w; 28 edge[top].nex = e[y]; 29 e[y] = top; 30 return; 31 } 32 33 inline bool SPFA(int s, int t) { 34 memset(d, 0x3f, sizeof(d)); 35 d[s] = 0; 36 flow[s] = INF; 37 vis[s] = 1; 38 Q.push(s); 39 while(!Q.empty()) { 40 int x = Q.front(); 41 Q.pop(); 42 vis[x] = 0; 43 for(int i = e[x]; i; i = edge[i].nex) { 44 int y = edge[i].v; 45 if(edge[i].c && d[y] > d[x] + edge[i].len) { 46 d[y] = d[x] + edge[i].len; 47 pre[y] = i; 48 flow[y] = std::min(flow[x], edge[i].c); 49 if(!vis[y]) { 50 vis[y] = 1; 51 Q.push(y); 52 } 53 } 54 } 55 } 56 return d[t] < INF; 57 } 58 59 inline void update(int s, int t) { 60 int temp = flow[t]; 61 while(t != s) { 62 int i = pre[t]; 63 edge[i].c -= temp; 64 edge[i ^ 1].c += temp; 65 t = edge[i ^ 1].v; 66 } 67 return; 68 } 69 70 inline int solve(int s, int t, int &cost) { 71 int ans = 0; 72 cost = 0; 73 while(SPFA(s, t)) { 74 ans += flow[t]; 75 cost += flow[t] * d[t]; 76 update(s, t); 77 } 78 return ans; 79 } 80 81 int m; 82 inline int id(int x, int y) { 83 return (x - 1) * m + y; 84 } 85 86 int main() { 87 88 int n; 89 scanf("%d%d", &m, &n); 90 for(int i = 1; i <= n; i++) { 91 for(int j = 1; j <= m; j++) { 92 scanf("%d", &G[i][j]); 93 } 94 } 95 int s = (m + 1) * n + 1; 96 int t = s + 1; 97 for(int a = 1; a <= n; a++) { 98 add(s, a, 1, 0); 99 for(int j = 1; j <= m; j++) { 100 for(int i = 1; i <= n; i++) { 101 add(a, n + id(i, j), 1, i * G[a][j]); 102 } 103 } 104 for(int j = 1; j <= m; j++) { 105 add(n + id(a, j), t, 1, 0); 106 } 107 } 108 int ans; 109 solve(s, t, ans); 110 printf("%.2f", 1.0 * ans / n); 111 return 0; 112 }