1. 程式人生 > >洛谷P2053 修車

洛谷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 }
AC程式碼