洛谷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代码

 

posted @ 2018-12-12 20:57  huyufeifei  阅读(154)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜