人生有信仰 数据有梯度 暴力不爆零


bzoj 1070: [SCOI2007]修车 -- 费用流

1070: [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 128 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)

 

Source

 

  把每个工人拆成N个点。记为A[i,j]表示第i个工人修倒数第j辆车。

  每个车跟所有N*M个工人拆出的点连边。流量为1,费用为time[i,j]*k。

  源和每辆车连边,N*M个点和汇连边,流量都为1,费用同为0。

#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define N 2010
#define M 100010
#define inf 100000007
int T=1001;
int fro[M],to[M],lj[N],v[M],w[M],fa[M],cnt=1;
void add(int a,int b,int c,int d){fro[++cnt]=lj[a];to[cnt]=b;fa[cnt]=a;v[cnt]=c;w[cnt]=d;lj[a]=cnt;}
void ins(int a,int b,int c,int d){add(a,b,c,d);add(b,a,0,-d);}
int dis[N],q[N],from[N],ans;
bool vs[N];
bool spfa()
{
    memset(dis,0x3f,sizeof(dis));
    int h=0,t=1,x;
    dis[0]=q[0]=0;vs[0]=1;
    while(h!=t)
    {
        x=q[h++];
        if(h==T) h=0;
        for(int i=lj[x];i;i=fro[i])
        {
            if(v[i]&&dis[to[i]]>dis[x]+w[i])
            {
                dis[to[i]]=dis[x]+w[i];
                from[to[i]]=i;
                if(!vs[to[i]])
                {
                    vs[to[i]]=1;
                    q[t++]=to[i];if(t==T) t=0;
                }
            }
        }
        vs[x]=0;
    }
    return dis[T]<inf;
}
void qaz()
{
    int tmp=inf;
    for(int i=from[T];i;i=from[fa[i]]) tmp=min(tmp,v[i]);
    for(int i=from[T];i;i=from[fa[i]])
    {
        v[i]-=tmp;v[i^1]+=tmp;
        ans+=w[i]*tmp;
    }
}
int n,m,t[66][12];
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) scanf("%d",&t[i][j]);
    for(int i=1;i<=m*n;i++) ins(0,i,1,0);
    for(int i=m*n+1;i<=m*n+n;i++) ins(i,T,1,0);
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++)
                ins((i-1)*n+j,n*m+k,1,t[k][i]*j);
    while(spfa()) qaz();
    printf("%.2lf\n",ans*1.0/n);
    return 0;
}

 

posted @ 2017-04-30 22:14  lkhll  阅读(212)  评论(0编辑  收藏  举报