bzoj1070: [SCOI2007]修车

题目链接

bzoj1070

题目描述

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)

题解

这题每个顾客的等待时间也要计算,这便是麻烦之处。
考虑第i个人修第j辆车,如果这辆车是倒数第k台被修理的,那么k辆车都有等待t的时间,相当于费用为t[j,i]* k。那么我们把m个人拆成n*m个点,每个人的第i个点代表他修理的车是倒数第i辆,将这个点分别向n辆车连边,费用为i *t。跑一遍费用流就行了。其实就相当于将所有情况的费用提前计算出来。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

#define N 605
struct edge{
    int x,next,cost,data,f;
}e[100000];
int first[N],c[N*N],v[N],dis[N],ti[N][N],pre[N],tot=1,n,m,p,q,s,t;

void add(int x,int y,int d,int c){
    e[++tot].x=y;
    e[tot].data=d;
    e[tot].cost=c;
    e[tot].f=x;
    e[tot].next=first[x];
    first[x]=tot;
    if(~tot&1) add(y,x,0,-c); 
} 
bool spfa(){
    memset(dis,63,sizeof(dis));
    memset(v,0,sizeof(v));
    v[c[1]=s]=1; dis[s]=0;
    for(p=q=1;p<=q;v[c[p]]=0,p++)
     for(int i=first[c[p]];i;i=e[i].next)
     if(e[i].data&&dis[e[i].x]>dis[c[p]]+e[i].cost){
        dis[e[i].x]=dis[c[p]]+e[i].cost;
        pre[e[i].x]=i;
        if(!v[e[i].x]) v[c[++q]=e[i].x]=1;
     }
    return dis[t]!=dis[0];
}
int cost_flow(){
    int ans=0,flow;
    while(spfa()){
        flow=1000000007;
        for(int i=pre[t];i;i=pre[e[i].f]) flow=min(flow,e[i].data);
        ans+=flow*dis[t];
        for(int i=pre[t];i;i=pre[e[i].f]) e[i].data-=flow,e[i^1].data+=flow;
    }
    return ans;
}
int main(){
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++) scanf("%d",&ti[i][j]);
    s=n*m+n+1; t=n*m+n+2;
    for(int i=1;i<=n*m;i++) add(s,i,1,0);
    for(int i=1;i<=n;i++) add(i+n*m,t,1,0);
    for(int i=1;i<=m;i++)
     for(int j=1;j<=n;j++)
      for(int k=1;k<=n;k++) add((i-1)*n+k,n*m+j,1,ti[j][i]*k);
    printf("%.2f",(double)cost_flow()/n);
    return 0;
}

你可能感兴趣的:(bzoj1070: [SCOI2007]修车)