zoukankan      html  css  js  c++  java
  • [BZOJ 1070] [SCOI2007] 修车

    1070: [SCOI2007]修车

    Time Limit: 1 Sec
    Memory Limit: 162 MB

    Description

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

    Input

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

    Output

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

    Sample Input

    2 2
    3 2
    1 4

    Sample Output

    1.50

    HINT

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

    【题解】

    设time[i][j]表示第i部车被第j个修理人员修的时间.

    把每个维修人员拆成n个点,表示是倒数第几个修的.再建n个点表示n部车.

    那么如果第i部车,是在第j个维修人员那里作为倒数第z个修,那么就像i->(j,z)连一条费用(影响)是 time[i][j]*z (要加上自己的哦.),容量为1的边.

    再向源点到n部车的点连一条容量为1费用为0的边,表示每部车只有一辆.

    每个表示第j个维修人员,倒数第z个修的点(j,z)向汇点连一条容量为1费用为0的边,表示第j个维修人员,倒数第z个修的车,只能有一辆.

    这构图真是机智。。。然而我太弱了只好多见识见识机智的构图模型咯

    现在费用流写的有点熟了呢~

     1 #include <stdio.h>
     2 #include <queue>
     3 #include <string.h>
     4 using namespace std;
     5 const int B=200100;
     6 int head[B], timx[1010][1010], S, T, n, m, cnt=-1, next[B], to[B], w[B], flow[B], d[B], pre[B];
     7 bool vis[B];
     8 int oq[B];
     9 int ans;
    10 double ans2;
    11 queue<int> q;
    12 
    13 inline void qclean() {
    14     while(!q.empty()) q.pop();
    15 }
    16 inline void addf(int u,int v,int _flow,int _w) {
    17     ++cnt;
    18     to[cnt]=v;
    19     next[cnt]=head[u];
    20     head[u]=cnt; 
    21     flow[cnt]=_flow;
    22     w[cnt]=_w;
    23 }
    24 inline void add(int u,int v,int _flow,int _w) {
    25     addf(u,v,_flow,_w);
    26     addf(v,u,0,-_w);
    27 }
    28 inline bool spfa() {
    29     qclean();
    30     memset(d,0X7f,sizeof(d));
    31     memset(vis,0,sizeof(vis));
    32     memset(oq,0,sizeof(oq));
    33     memset(pre,-1,sizeof(pre));
    34     pre[S]=-1; d[S]=0; vis[S]=1; q.push(S);
    35     while(!q.empty()) {
    36         int top=q.front(); q.pop();
    37         vis[top]=0;
    38         for (int i=head[top];i>=0;i=next[i]) {
    39             if(d[top]+w[i]<d[to[i]]&&flow[i]) {
    40                 d[to[i]]=d[top]+w[i];
    41                 pre[to[i]]=i;
    42                 if(!vis[to[i]]) {
    43                     vis[to[i]]=1;
    44                     q.push(to[i]);
    45                 }
    46             }
    47         }
    48     }
    49     return pre[T]!=-1;
    50 }
    51 inline void mcf() {
    52     int xm=1e9;
    53     for (int k=pre[T];k>=0;k=pre[to[k^1]]) 
    54         xm=min(xm,flow[k]);
    55     for (int k=pre[T];k>=0;k=pre[to[k^1]]) {
    56         flow[k]-=xm;
    57         flow[k^1]+=xm;
    58         ans+=xm*w[k];
    59     }
    60 }
    61 int main() {
    62     scanf("%d%d",&m,&n);
    63     S=0; T=n*m+n+1;
    64     memset(head,-1,sizeof(head));
    65     for (int i=1;i<=n;++i) 
    66         for (int j=1;j<=m;++j) scanf("%d",&timx[i][j]);
    67     for(int i=1;i<=n;i++) add(S,i,1,0);
    68     for(int i=n+n*m;i>=n+1;i--) add(i,T,1,0);
    69     for(int i=1;i<=n;i++)
    70         for(int j=1;j<=m;j++)
    71             for(int k=1;k<=n;k++)
    72                  add(i,j*n+k,1,(n-k+1)*timx[i][j]);
    73     while(spfa()) mcf();
    74     printf("%.2lf
    ",(double)ans/n);
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    实战 Windows下搭建Objectivec的编译环境
    C# 协变和逆变 精解(直观明了,简单易懂)
    求两个字符串的最大公共串
    [C++][数据结构]队列(queue)的实现
    转换一个矩阵(2维数组)为HTML Table
    [C++][数据结构][算法]单链式结构的深拷贝
    LaTeX 中的特殊符号
    [C++11][数据结构]自己的双链表实现
    现代诗十则
    [C++11][算法][穷举]输出背包问题的所有可满足解
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/bzoj1070.html
Copyright © 2011-2022 走看看