2
22
2016
0

【bzoj1070】【SCOI2007】修车

1070: [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 3721  Solved: 1507
[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)

#include<cstdio>
#define INF 1000000000
using namespace std;
int n,m,tot,edgenum,ans;
int id[100][100],Id[100],a[100][100];
int vet[500010],next[500010],head[500010],maxv[500010],cost[500010],dis[500010],flag[500010],q[500010],last[500010],pre[500010];
void add(int u,int v,int w,int z)
{
    vet[++edgenum]=v;
    next[edgenum]=head[u];
    head[u]=edgenum;
    maxv[edgenum]=w;
    cost[edgenum]=z;
}
int spfa()
{
    for (int i=0;i<=tot;i++){dis[i]=INF;flag[i]=0;}
    int p1=-1,p2=0;
    q[0]=0;dis[0]=0;flag[0]=1;
    while (p1<p2)
    {
        int u=q[++p1];
        flag[u]=0;
        for (int e=head[u];e;e=next[e])
        {
            if (maxv[e]<=0) continue;
            int v=vet[e];
            if (dis[u]+cost[e]<dis[v])
            {
                dis[v]=dis[u]+cost[e];
                last[v]=e;pre[v]=u;
                if (!flag[v]){flag[v]=1;q[++p2]=v;}
            }
        }
    }
    if (dis[tot]==INF) return 0;else return 1;
}
void work()
{
    ans+=dis[tot];
    int u=tot;
    while (u)
    {
        int e=last[u];
        maxv[e]--;
        if (e%2) maxv[e+1]++;else maxv[e-1]++;
        u=pre[u];
    }
}
int main()
{
    scanf("%d%d",&m,&n);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            scanf("%d",&a[j][i]);
    for (int i=1;i<=m;i++)
        for (int j=1;j<=n;j++)
            id[i][j]=++tot;
    for (int i=1;i<=n;i++)
        Id[i]=++tot;
    tot++;
    for (int i=1;i<=n;i++){add(0,Id[i],1,0);add(Id[i],0,0,0);}
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            for (int k=1;k<=n;k++){add(Id[i],id[j][k],1,a[j][i]*k);add(id[j][k],Id[i],0,-a[j][i]*k);}
    for (int i=1;i<=m;i++)
        for (int j=1;j<=n;j++){add(id[i][j],tot,1,0);add(tot,id[i][j],0,0);}
    while (spfa()) work();
    printf("%.2lf\n",(double)ans/n);
}

Category: 网络流 | Tags: | Read Count: 438

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com