$ \color{#0066ff}{ 题目描述 }$

同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。

说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。

\(\color{#0066ff}{输入格式}\)

第一行有两个数M,N,表示技术人员数与顾客数。

接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。

\(\color{#0066ff}{输出格式}\)

最小平均等待时间,答案精确到小数点后2位。

\(\color{#0066ff}{输入样例}\)

  1. 2 2
  2. 3 2
  3. 1 4

\(\color{#0066ff}{输出样例}\)

  1. 1.50

\(\color{#0066ff}{数据范围与提示}\)

(2<=M<=9,1<=N<=60), (1<=T<=1000)

\(\color{#0066ff}{题解}\)

这种对应关系还有数据范围,显然就是费用流了

现在的问题是怎么建边

发现,每辆车的等待时间跟前面修车人所修的车有关

假设某人修了10辆车

那么他修第一辆的时候,后面9人都等了这个时间,也就是贡献+=9倍的这个时间

因此我们单独考虑这个人修的每一辆车对时间的贡献

把每个人都拆成n个点

对于一个人的第k个点,连向它的车代表他倒数第k次修它

也就是连T*k的边权,倒数第k次修它,那么后面k辆车就会产生这么多贡献

跑一遍费用流即可(zkw大法好)

  1. // luogu-judger-enable-o2
  2. #include<bits/stdc++.h>
  3. #define LL long long
  4. LL in() {
  5. char ch; LL x = 0, f = 1;
  6. while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
  7. for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
  8. return x * f;
  9. }
  10. const int maxn = 1e5 + 10;
  11. const int inf = 0x7fffffff;
  12. struct node {
  13. int to, can, dis;
  14. node *nxt, *rev;
  15. node(int to = 0, int can = 0, int dis = 0, node *nxt = NULL): to(to), can(can), dis(dis), nxt(nxt) {
  16. rev = NULL;
  17. }
  18. };
  19. node *head[maxn], *cur[maxn];
  20. bool vis[maxn];
  21. int n, m, s, t;
  22. int dis[maxn];
  23. void add(int from, int to, int can, int dis) {
  24. head[from] = new node(to, can, dis, head[from]);
  25. }
  26. void link(int from, int to, int can, int dis) {
  27. add(from, to, can, dis);
  28. add(to, from, 0, -dis);
  29. head[from]->rev = head[to];
  30. head[to]->rev = head[from];
  31. }
  32. bool spfa() {
  33. std::queue<int> q;
  34. for(int i = s; i <= t; i++) dis[i] = inf, vis[i] = false;
  35. q.push(t);
  36. dis[t] = 0;
  37. while(!q.empty()) {
  38. int tp = q.front(); q.pop();
  39. vis[tp] = false;
  40. for(node *i = head[tp]; i; i = i->nxt) {
  41. if(dis[i->to] > dis[tp] - i->dis && i->rev->can) {
  42. dis[i->to] = dis[tp] - i->dis;
  43. if(!vis[i->to]) {
  44. q.push(i->to);
  45. vis[i->to] = true;
  46. }
  47. }
  48. }
  49. }
  50. return dis[s] != inf;
  51. }
  52. int dfs(int x, int change) {
  53. if(x == t || !change) return change;
  54. int flow = 0, ls;
  55. vis[x] = true;
  56. for(node *i = head[x]; i; i = i->nxt) {
  57. if(!vis[i->to] && dis[i->to] == dis[x] - i->dis && (ls = dfs(i->to, std::min(change, i->can)))) {
  58. flow += ls;
  59. change -= ls;
  60. i->can -= ls;
  61. i->rev->can += ls;
  62. if(!change) break;
  63. }
  64. }
  65. return flow;
  66. }
  67. int zkw() {
  68. int cost = 0;
  69. while(spfa()) {
  70. vis[t] = true;
  71. while(vis[t]) {
  72. for(int i = s; i <= t; i++) vis[i] = false;
  73. cost += dis[s] * dfs(s, inf);
  74. }
  75. }
  76. return cost;
  77. }
  78. int main() {
  79. m = in(), n = in(), s = 0, t = m * n + n + 1;
  80. for(int i = 1; i <= m; i++)
  81. for(int j = 1; j <= n; j++)
  82. link(s, (i - 1) * n + j, 1, 0);
  83. for(int i = 1; i <= n; i++) link(m * n + i, t, 1, 0);
  84. for(int i = 1; i <= n; i++)
  85. for(int j = 1; j <= m; j++) {
  86. int x = in();
  87. for(int k = 1; k <= n; k++) link((j - 1) * n + k, n * m + i, 1, k * x);
  88. }
  89. printf("%.2f\n", (double)zkw() / n);
  90. return 0;
  91. }

P2053 [SCOI2007]修车 费用流的更多相关文章

  1. bzoj 1070: [SCOI2007]修车 费用流

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2785  Solved: 1110[Submit][Status] ...

  2. [BZOJ1070][SCOI2007]修车 费用流

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 6209  Solved: 2641[Submit][Status] ...

  3. 【BZOJ1070】[SCOI2007]修车 费用流

    [BZOJ1070][SCOI2007]修车 Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的. ...

  4. [bzoj1070][SCOI2007]修车——费用流

    题目大意: 传送门 题解: 本题和(POJ3686)[http://poj.org/problem?id=3686]一题一模一样,而且还是数据缩小以后的弱化版QAQ,<挑战程序设计竞赛>一 ...

  5. [BZOJ1070] [SCOI2007] 修车 (费用流 & 动态加边)

    Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使 ...

  6. 【BZOJ 1070】[SCOI2007]修车 费用流

    就是拆个点限制一下(两点一排一大片),这道题让我注意到了限制这个重要的词.我们跑网络流跑出来的图都是有一定意义的,一般这个意义就对应了问题的一种方案,一般情况下跑一个不知道对不对的方案是相对容易的我们 ...

  7. [SCOI2007]修车 费用流

    ---题面--- 题解: 因为我们并不需要知道准确方案,而人数固定,要使得平均等待时间最小,也就是要使得总的等待时间最小. 因此我们将工人按每个时刻拆点,拆完之后向车子连边,流量为1,费用为k * 维 ...

  8. [SCOI2007]修车 费用流 BZOJ 1070

    题目描述 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待 ...

  9. BZOJ.1070.[SCOI2007]修车(费用流SPFA)

    题目链接 /* 神tm看错题*2.. 假如人员i依次维修W1,W2,...,Wn,那么花费的时间是 W1 + W1+W2 + W1+W2+W3... = W1*n + W2*(n-1) + ... + ...

随机推荐

  1. swift一次 Attempt to present on whose view is not in the window hierarchy的解决方法

    做的是二维码扫描,扫描后识别为URL的话就跳转到webview 加载网页,用的是代理传值的方式.扫描到了 值传递到主页 扫描窗体退出,检测值是否是http://开头 是网页就跳转. 问题出在传值到主界 ...

  2. Jquery改变td内容为1的颜色

    Jquery改变td内容为1的颜色<table id="tb" > <tr> <td val="1">1</td> ...

  3. JS中日期处理

  4. 动画系统II

    [动画系统II] 1.动画混合(animation blending)是把某个时间点的两个或更多的输入姿势结合,产生骨骼的输出姿势.例如,通过混合负伤的及无负伤的步行动画,我们可以生成二者之间不同负伤 ...

  5. java基础之JDBC九:DbUtils的简介及使用

    DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能. 使用步骤: A: 获取可以执行SQL语句的对象. pu ...

  6. 无限极分类的JS实现

    纯JS实现无限极分类 <!DOCTYPE html> <html> <head> <title></title>//引入Jquery < ...

  7. 在页面完成读取EXCEL

    protected void btnUpload_Click(object sender, EventArgs e) { if (Page.IsValid) { string sFILENAME = ...

  8. PHP中 null ,false , 区别

    先来测试一下吧: if(0 ==''){ echo '<br/>在PHP中0 ==\'\'' ; } if(0 !==''){ echo '<br/>在PHP中0 !==\'\ ...

  9. [redis]redis-cluster搭建

    1.概述: redis是一种工作在内存里no-sql的非关系型数据库,广泛应用于缓存需求,以减少大量的数据访问对数据库的压力,还很适合用来充当整个互联网架构中各级之间的cache 比如lvs的4层转发 ...

  10. (字符串)ZigZag Conversion

    [解析] 第一次看到这个题目的人,可能不知道ZigZag是什么意思,简单解释一下,就是把字符串原顺序012345……按下图所示排列: 发现所有行的重复周期都是 2 * nRows - 2 对于首行和末 ...