BZOJ 1070: [SCOI2007]修车 [最小费用最大流]

1070: [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 4936  Solved: 2032
[Submit][Status][Discuss]

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)


理解错了题意:每个人可以修多辆车
 
每个人拆成n个点,对于他修的倒数第一辆代价就是1*time,倒数第二辆就是2*time,一次类推
每个点都像车连一条容量为1,代价为以上时间的边
s连所有人,t连所有车,跑费用流即可
 
注意先m后n
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1005,M=1e5+5,INF=1e9;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
    return x*f;
}
int n,m,a[N][N],s,t;
struct edge{
    int v,ne,c,f,w;
}e[M<<1];
int cnt,h[N];
inline void ins(int u,int v,int c,int w){
    cnt++;
    e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].w=w;
    e[cnt].ne=h[u];h[u]=cnt;
    cnt++;
    e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].w=-w;
    e[cnt].ne=h[v];h[v]=cnt;
}
inline int id(int i,int j){return (i-1)*n+j;}
void build(){
    s=0;t=m*n+n+1;int num=m*n;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++){
            int t=id(i,j);
            ins(s,t,1,0);
            for(int k=1;k<=n;k++) ins(t,num+k,1,a[i][k]*j);
        }
    for(int i=1;i<=n;i++) ins(num+i,t,1,0);
}


int q[N],head,tail,d[N],inq[N],pre[N],pos[N];
inline void lop(int &x){if(x==N) x=1;else if(x==0) x=N-1;}
bool spfa(){
    memset(d,127,sizeof(d));
    memset(inq,0,sizeof(inq));
    head=tail=1;
    q[tail++]=s;inq[s]=1;d[s]=0;
    pre[t]=-1;
    while(head!=tail){
        int u=q[head++];inq[u]=0;lop(head);
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v,w=e[i].w;
            if(e[i].c>e[i].f&&d[v]>d[u]+w){
                d[v]=d[u]+w;
                pos[v]=i;pre[v]=u;
                if(!inq[v]){
                    inq[v]=1;
                    if(d[v]<d[q[head]]) head--,lop(head),q[head]=v;
                    else q[tail++]=v,lop(tail);
                }
            }
        }
    }
    return pre[t]!=-1;
}
int mcmf(){
    int flow=0,cost=0;
    while(spfa()){
        int f=INF;
        for(int i=t;i!=s;i=pre[i]) f=min(f,e[pos[i]].c-e[pos[i]].f);
        flow+=f;cost+=d[t]*f;
        for(int i=t;i!=s;i=pre[i]){
            int p=pos[i];
            e[p].f+=f;
            e[((p-1)^1)+1].f-=f;
        }
    }
    return cost;
}
int main(){
    m=read();n=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) a[j][i]=read();//
    build();
    printf("%.2f",(double)mcmf()/n);
}

 

posted @ 2016-12-16 19:04  Candy?  阅读(260)  评论(0编辑  收藏  举报