zoukankan      html  css  js  c++  java
  • 1070. [SCOI2007]修车【费用流】

    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)

    将M个工作人员拆成N个点
    拆后的M员工的第k个裂点连某辆车,表示该车是倒数第k个被修的车
    因为是倒数第k,所以费用自然要加上后面排队的车的费用
    算是一种逆向思维吧
    MD n和m搞反了……找错找了半天qwq

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<queue>
      6 #define MAXN (50000+10)
      7 #define MAXM (5000000+10)
      8 using namespace std;
      9 queue<int>q;
     10 bool visit[MAXN];
     11 int pre[MAXN];
     12 int n,m,k,s,e=4999,Ans,Fee;
     13 int num_edge;
     14 int head[MAXN];
     15 int dis[MAXN];
     16 bool used[MAXN];
     17 int INF;
     18 int t[1000][1000];
     19 struct node
     20 {
     21     int to;
     22     int next;
     23     int Flow;//残留网络
     24     int Cost;
     25 } edge[MAXM*2];
     26 
     27 void add(int u,int v,int l,int c)
     28 {
     29     edge[++num_edge].to=v;
     30     edge[num_edge].next=head[u];
     31     edge[num_edge].Flow=l;
     32     edge[num_edge].Cost=c;
     33     head[u]=num_edge;
     34 }
     35 
     36 bool Spfa(int s,int e)
     37 {
     38     memset(pre,-1,sizeof(pre));
     39     memset(dis,0x7f,sizeof(dis));
     40     q.push(s);
     41     dis[s]=0;
     42     used[s]=true;
     43     while (!q.empty())
     44     {
     45         int x=q.front();
     46         q.pop();
     47         for (int i=head[x]; i!=0; i=edge[i].next)
     48             if (dis[x]+edge[i].Cost<dis[edge[i].to] && edge[i].Flow>0)
     49             {
     50                 dis[edge[i].to]=edge[i].Cost+dis[x];
     51                 pre[edge[i].to]=i;
     52                 if (!used[edge[i].to])
     53                 {
     54                     used[edge[i].to]=true;
     55                     q.push(edge[i].to);
     56                 }
     57             }
     58         used[x]=false;
     59     }
     60     return (dis[e]!=INF);
     61 }
     62 
     63 int MCMF(int s,int e)
     64 {
     65     Ans=0,Fee=0;
     66     while (Spfa(s,e))
     67     {
     68         int d=INF;
     69         for (int i=e; i!=s; i=edge[((pre[i]-1)^1)+1].to)
     70             d=min(d,edge[pre[i]].Flow);
     71         for (int i=e; i!=s; i=edge[((pre[i]-1)^1)+1].to)
     72         {
     73             edge[pre[i]].Flow-=d;
     74             edge[((pre[i]-1)^1)+1].Flow+=d;
     75         }
     76         Ans+=d;
     77         Fee+=d*dis[e];
     78     }
     79     return Fee;
     80 }
     81 
     82 int main()
     83 {
     84     memset(&INF,0x7f,sizeof(INF));
     85     scanf("%d%d",&m,&n);
     86     for (int i=1;i<=n;++i)
     87         for (int j=1;j<=m;++j)
     88             scanf("%d",&t[i][j]);
     89     for (int i=1;i<=m*n;++i)
     90     {
     91         add(s,i,1,0);
     92         add(i,s,0,0);
     93     }
     94     for (int i=1;i<=n;++i)
     95     {
     96         add(m*n+i,e,1,0);
     97         add(e,m*n+i,0,0);
     98     }
     99     for (int i=1;i<=n;++i)
    100         for (int j=1;j<=m;++j)
    101             for (int k=1;k<=n;++k)
    102             {
    103                 add((j-1)*n+i,m*n+k,1,i*t[k][j]);
    104                 add(m*n+k,(j-1)*n+i,0,-i*t[k][j]);
    105             }
    106     double ans=MCMF(s,e);
    107     printf("%.2lf
    ",ans/n);
    108 }
  • 相关阅读:
    编译OpenCV文档
    opencv笔记5:频域和空域的一点理解
    opencv笔记4:模板运算和常见滤波操作
    opencv笔记3:trackbar简单使用
    opencv笔记2:图像ROI
    opencv笔记1:opencv的基本模块,以及环境搭建
    php复习
    fedora安装软件
    win10更换登陆背景和关闭锁屏
    svn服务器配置以及自动同步到web服务器
  • 原文地址:https://www.cnblogs.com/refun/p/8679209.html
Copyright © 2011-2022 走看看