zoukankan      html  css  js  c++  java
  • [luogu]P2053 [SCOI2007]修车

    原题链接:P2053 [SCOI2007]修车

    题意

    有$n$辆车要修,有$m$个修理工,第$j$修理工修第$i$辆车有一个时间$r_{j,i}$。

    求顾客最少的平均等待时间。

    分析

    由于$n$是给定的,所以最小的平均等待时间就是要求最小的总时间。

    我们考虑怎么让总时间最短。

    很容易发现第$i$辆车放在第$j$名修理工修,在$i$后面$j$还有还有$k$辆车要修时,$i$对总时间的贡献为$r_{j,i}*(n-p+1)$。

    然后就可以用费用流解决这个问题。

    我们可以把每个修理工拆成$n$个修理工,第$p$个修理工代表后面还有$n-p$辆车要修。

    左边$n$个点表示车,右边$m*n$个点表示修理工,(以下所有边的容量均为1),源点向车连0边,车向修理工连$r_{j,i}*(n-p+1)$边,修理工向汇点连0边,跑最小费用最大流即可。

    代码

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N=107,M=17;
     4 const int Ma=1000009;
     5 int read(){
     6     char c;int num,f=1;
     7     while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
     8     while(c=getchar(), isdigit(c))num=num*10+c-'0';
     9     return f*num;
    10 }
    11 queue <int> q;
    12 int n,m,maxflow,ans,r[M][N],dis[Ma],vis[Ma],pre[Ma],flow[Ma];
    13 int head[Ma],nxt[Ma],ver[Ma],cost[Ma],edge[Ma],tot=1,s,t;
    14 void add(int u,int v,int w,int f){
    15     ver[++tot]=v;nxt[tot]=head[u];head[u]=tot;edge[tot]=w;cost[tot]=f;
    16 }
    17 bool spfa(){
    18     while(q.size())q.pop();
    19     memset(dis,0x3f,sizeof(dis));dis[s]=0;
    20     memset(vis,0   ,sizeof(vis));vis[s]=1;
    21     q.push(s);flow[s]=0x3f3f3f3f;
    22     while(q.size()){
    23         int x=q.front();
    24         vis[x]=0;q.pop();
    25         for(int i=head[x];i;i=nxt[i])if(edge[i]){
    26             int y=ver[i];
    27             if(dis[y]>dis[x]+cost[i]){
    28                 dis[y]=dis[x]+cost[i];
    29                 pre[y]=i;
    30                 flow[y]=min(flow[x],edge[i]);
    31                 if(!vis[y]){
    32                     q.push(y);
    33                     vis[y]=1;
    34                 }
    35             }
    36         }
    37     }
    38     return dis[t]!=0x3f3f3f3f;
    39 }
    40 void update(){
    41     int x=t;
    42     while(x!=s){
    43         int i=pre[x];
    44         edge[i]-=flow[t];
    45         edge[i^1]+=flow[t];
    46         x=ver[i^1];
    47     }
    48     maxflow+=flow[t];
    49     ans+=dis[t]*flow[t];
    50 }
    51 int main()
    52 {
    53     m=read();n=read();
    54     s=0;t=(m+1)*n+1;
    55     for(int i=1;i<=n;i++)
    56         for(int j=1;j<=m;j++)
    57             r[j][i]=read();
    58     for(int i=1;i<=n;i++){
    59         add(s,i,1,0);
    60         add(i,s,0,0);
    61     }
    62     for(int j=1;j<=m;j++){
    63         for(int p=1;p<=n;p++){
    64             for(int i=1;i<=n;i++){
    65                 add(i,j*n+p,1,r[j][i]*(n-p+1));
    66                 add(j*n+p,i,0,-r[j][i]*(n-p+1));
    67             }
    68             add(j*n+p,t,1,0);
    69             add(t,j*n+p,0,0);
    70         }
    71     }
    72     while(spfa())update();
    73     printf("%.2f
    ",1.0*ans/n);
    74     return 0;
    75 }
    76 
    77  
    View Code
  • 相关阅读:
    【NOI2008】志愿者招募
    【NOI2015】小园丁和老司机
    【TJOI2007】小朋友
    【HNOI2008】神奇的国度
    【CTSC2014】企鹅QQ
    【CQOI2014】通配符匹配
    【JSOI2008】火星人
    【SCOI2007】压缩
    【ZJOI2009】对称的正方形
    【LOJ#6066】同构子树
  • 原文地址:https://www.cnblogs.com/onglublog/p/10054071.html
Copyright © 2011-2022 走看看