zoukankan      html  css  js  c++  java
  • 图论(网络流):SCOI 2007 修车

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

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

    输入

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

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

    输出

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

    样例

    repair.in

    2 2

    3 2

    1 4

    repair.out

    1.50

    数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)

      网上的题解好多都特别粗略,我走了好多弯路。

      所以决定写详细一点:把每个修理工变为N个点,表示倒数第1~N个修理的车,为啥是倒数呢?因为不知道一个人究竟修了几辆车,又因为倒数第一的总比倒数第二的更优,费用流会优先倒数第一的,再倒数第二的,所以用倒数的可以很好地解决。多么的巧妙!!!然后是这样建图的:S向每个人的每个倒数第几维修的点连一条流量为1,费用为0的边;接着再新建N个点,代表N辆车,每个人的每个倒数第几维修的点向其连一条流量为1,费用为(当前是倒数第i个的i)*(第j个人修第k辆车的时间);最后由N辆车的向T连容量为1,费用为0的边。

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <queue>
     5 using namespace std;
     6 const int INF=1000000000;
     7 const int maxn=1010,maxm=400010;
     8 int cnt=1,fir[maxn],nxt[maxm],to[maxm];
     9 int cap[maxm],val[maxm],dis[maxn],path[maxn];
    10 
    11 void add(int a,int b,int c,int v){
    12     nxt[++cnt]=fir[a];to[cnt]=b;
    13     cap[cnt]=c;val[cnt]=v;fir[a]=cnt;
    14 }
    15 void addedge(int a,int b,int c,int v){
    16     add(a,b,c,v);
    17     add(b,a,0,-v);
    18 }
    19 
    20 int S,T;
    21 int vis[maxn];
    22 int Spfa(){
    23     deque<int>q;
    24     memset(dis,127,sizeof(dis));
    25     memset(vis,0,sizeof(vis));
    26     q.push_front(S);
    27     dis[S]=0;vis[S]=1;
    28     while(!q.empty()){
    29         int x=q.front();q.pop_front();vis[x]=0;
    30         for(int i=fir[x];i;i=nxt[i])
    31             if(cap[i]&&dis[x]+val[i]<dis[to[i]]){
    32                 dis[to[i]]=val[i]+dis[x];
    33                 path[to[i]]=i;
    34                 if(vis[to[i]])continue;
    35                 if(dis[to[i]]<dis[x])
    36                     q.push_front(to[i]);
    37                 else
    38                     q.push_back(to[i]);
    39                 vis[to[i]]=1;    
    40             }
    41     }
    42     return dis[T]==dis[T+1]?0:dis[T]; 
    43 }
    44 
    45 int Aug(){
    46     int p=T,f=INF;
    47     while(p!=S){
    48         f=min(f,cap[path[p]]);
    49         p=to[path[p]^1];
    50     }
    51     p=T;
    52     while(p!=S){
    53         cap[path[p]]-=f;
    54         cap[path[p]^1]+=f;
    55         p=to[path[p]^1];
    56     }
    57     return f;
    58 }
    59 
    60 int MCMF(){
    61     int ret=0,d;
    62     while(d=Spfa())
    63         ret+=Aug()*d;
    64     return ret;    
    65 }
    66 
    67 int n,m;
    68 int a[maxn][maxn];
    69 int main(){
    70     freopen("scoi2007_repair.in","r",stdin);
    71     freopen("scoi2007_repair.out","w",stdout);
    72     scanf("%d%d",&m,&n);
    73     S=0;T=n*m+n+1;
    74     for(int i=1;i<=n;i++){
    75         addedge(n*m+i,T,1,0);
    76         for(int j=1;j<=m;j++)
    77             addedge(S,(i-1)*m+j,1,0);
    78     }
    79     for(int i=1;i<=n;i++)
    80         for(int j=1;j<=m;j++)
    81             scanf("%d",&a[i][j]);
    82     
    83     for(int j=1;j<=m;j++)
    84         for(int i=1;i<=n;i++)
    85             for(int k=1;k<=n;k++)
    86                 addedge((i-1)*m+j,n*m+k,1,i*a[k][j]);
    87             
    88     printf("%.2f
    ",1.0*MCMF()/n);
    89     return 0;
    90 }
  • 相关阅读:
    Android特色开发(3):Google Map
    Android特色开发(4):桌面组件
    Android用户界面开发(19):ProgressBar
    每日英语:Fewer Foreigners Eye US Graduate Science Programs
    每日英语:My Adventures With Liquid Chicken
    每日英语:Hard Math: Adding Up Just How Little We Actually Move
    每日英语:Thousands of Thumbs Down for Chinese Red Cross
    每日英语:Rescuers Struggle to Reach Quake Victims
    每日英语:When Simplicity Is The Solution
    【转】Matlab图像处理函数:regionprops
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5661559.html
Copyright © 2011-2022 走看看