zoukankan      html  css  js  c++  java
  • [bzoj1070] 修车

      这周学习了费用流,就写了几题。其中有一题就是bzoj上的修车,看起来很丧,交了6次都是除了样例全wa(事实证明样例说明不了什么,还会误导你……)。

      题目大意:有m个技术人员n辆车,一个技术人员只能同时修一辆车,每个技术人员修某一辆车都有特定的时间。求最小的等待时间。

      思路分析:这是一道费用流的题目,不看算法基本想不到是费用流。

           那么问题来了:怎么建图!看这个题目就像是把技术人员拆点。按题意建图的话,边权不是确定的,所以考虑拆成倒数第一次,倒数第二次……的n个结点。

           这样边权只要设为(之后的车数+1,也就是倒数的次数)*修车时间,因为包括自己之后每辆车都要等这么多时间。

           然后跑一边费用流。

           注意到它是二分图,所以可以用更高效的算法求解。而我比较蒻,只打了最简单的spfa。

      注意事项:我连wa了6次,是因为我没有认真看题,而样例m=n,n和m读反了就挂了3次(感谢falldream学长帮我debug)!!后面3次是没仔细调完就交还是wa。

      下面附上代码:

     1 #include<cstdio>
     2 using namespace std;
     3 const int inf=2147483647;
     4 int n,m,tot=1,mx,q[1010],d[1010],pree[1010],h[1010];
     5 struct edge{int to,nxt,cst,cap;}e[400010];
     6 bool vis[1010];
     7 int mn(int x,int y){return x>y?y:x;}
     8 void add(int fr,int to,int cst,int cap)
     9 {
    10     e[++tot]={to,h[fr],cst,cap};h[fr]=tot;
    11     e[++tot]={fr,h[to],-cst,0};h[to]=tot;
    12 }
    13 void init()
    14 {
    15     scanf("%d%d",&m,&n);
    16     int a[10][61];
    17     for(int i=1;i<=n;i++)
    18         for(int j=1;j<=m;j++)
    19             scanf("%d",&a[j][i]);
    20     for(int j=1;j<=n;j++)
    21     {
    22         for(int i=1;i<=m;i++)
    23         {
    24             for(int k=1;k<=n;k++)
    25                 add(j,i*n+k,a[i][j]*k,1);//从车向技术人员倒数第k辆连容量1费用k*修车费的边 
    26             add(i*n+j,n*m+n+1,0,1);//从技术人员修的每辆车连向汇点容量1费用0的边 
    27         }
    28         add(0,j,0,1);//从源点连向每辆车容量1费用0的边 
    29     }
    30     mx=n;n=n*m+n+1;
    31 }
    32 bool spfa()
    33 {
    34     for(int i=1;i<=n;i++)d[i]=inf;
    35     int l=0,r=1;q[1]=0;vis[0]=1;
    36     while(l!=r)
    37     {
    38         int x=q[l=l==n?0:l+1];
    39         for(int i=h[x];i;i=e[i].nxt)
    40             if(e[i].cap&&e[i].cst+d[x]<d[e[i].to])
    41             {
    42                 int v=e[i].to;
    43                 pree[v]=i;
    44                 d[v]=d[x]+e[i].cst;
    45                 if(!vis[v])
    46                 {
    47                     if(d[v]>d[l+1])q[r=r==n?0:r+1]=v;
    48                     else q[l]=v,l=l==0?n:l-1;
    49                     vis[v]=1;
    50                 }
    51             }
    52         vis[x]=0;
    53     }
    54     return d[n]==inf?0:1;
    55 }
    56 float cf()
    57 {
    58     int cost=0,mm=0;
    59     while(spfa())
    60     {
    61         int mi=inf;
    62         for(int i=n;i;i=e[pree[i]^1].to)
    63             mi=mn(mi,e[pree[i]].cap);
    64         for(int i=n;i;i=e[pree[i]^1].to)
    65         {
    66             int ee=pree[i];
    67             e[ee].cap-=mi;
    68             e[ee^1].cap+=mi;
    69         }
    70         cost+=d[n]*mi;
    71         mm+=mi;
    72     }
    73     return mm==mx?cost:0;
    74 }
    75 int main()
    76 {
    77     init();
    78     printf("%.2f",cf()/mx);
    79     return 0;
    80 }
    本文由qrc出品,若不在本博客上看到,请与本人联系。 网址:http://www.cnblogs.com/qrcer
  • 相关阅读:
    Eclipse SVN忽略某些文件或文件夹方法
    在ORACLE中给已有数据的表增加、修改、删除一个字段(或一个列)或者多个字段(或多个列)的问题
    Java中IO流,输入输出流概述与总结
    Java面向对象之继承
    jquery-each()
    window.showModalDialog以及window.open用法简介
    struts1、ajax、jquery、json简单实例
    软件人才管理
    疑难杂症定位记录
    linux中断子系统
  • 原文地址:https://www.cnblogs.com/qrcer/p/6592226.html
Copyright © 2011-2022 走看看