[SCOI2007]修车

题目描述

同一时刻有位车主带着他们的爱车来到了汽车维修中心。

维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。

现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。

说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。

输入

第一行有两个m,n,表示技术人员数与顾客数。

接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。

输出

样例输入

2 2
3 2
1 4

样例输出

1.50

提示

2<=M<=9,1<=N<=60 , 1<=T<=1000

费用流

建一个源点S与汇点T,

把S向每辆车连容量为1,费用为0的边,表示每辆车只被修一次

把每个技术人员拆n个点,第j个技术人员拆的第i个点表示第j个人倒数第i个修车

把拆出来的每个点向T连容量为1,费用为0的边

每辆车向每个点连边,流量1,费用是(之后的车的数量+1)*修它的时间。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int inq[100000],d[100000],h[100000],q[200000],from[100000],head,tail,k=1,INF=999999999,ans=0,used[100000];
int a[61][10];
struct data{
    int to,cap,cost,next;
}g[1000000];
void add(int from,int to,int cap,int cost)
{
    g[++k].next=h[from];h[from]=k;g[k].to=to;g[k].cap=cap;g[k].cost=cost;
    g[++k].next=h[to];h[to]=k;g[k].to=from;g[k].cap=0;g[k].cost=-cost;
}
bool spfa(int s,int t)
{
    head=tail=100000;
    memset(d,127/3,sizeof(d));INF=d[0];
    memset(inq,0,sizeof(inq));
    q[tail++]=t;d[t]=0;inq[t]=1;
    while(head<=tail) 
    {
        int u=q[head++];inq[u]=0;
        for(int i=h[u];i;i=g[i].next)
        {
            if(g[i^1].cap&&d[u]+g[i^1].cost<d[g[i].to])
            {
                d[g[i].to]=d[u]+g[i^1].cost;
                if(!inq[g[i].to])
                {
                    if(d[g[i].to]<d[q[head]])q[--head]=g[i].to;
                    else q[tail++]=g[i].to;inq[g[i].to]=1;
                }
            }
        }
    }
    return d[s]!=INF;
 } 
int dfs(int u,int t,int f)
{
    used[u]=1;
    if(u==t)return f;
    int _used=0,w;
    for(int i=h[u];i;i=g[i].next)
    {
        if(!used[g[i].to]&&g[i].cap&&d[u]-g[i].cost==d[g[i].to])
        {
            w=dfs(g[i].to,t,min(g[i].cap,f-_used));
            if(w)
            {
                _used+=w;g[i].cap-=w;g[i^1].cap+=w;ans+=w*g[i].cost;
                if(_used==f)return f;
            }
        }
    }
    return _used;
}
void PD(int s,int t)
{
    while(spfa(s,t))
    {
        used[t]=1;
        while(used[t])
        {
            memset(used,0,sizeof(used));
            dfs(s,t,INF);
        }
    }
}
int main()
{
    int m,n;scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        scanf("%d",&a[i][j]);
    }
    int S=n+n*m+1,T=n+n*m+2;
    for(int i=n+1;i<=n*m+n;i++)add(i,T,1,0);
    for(int i=1;i<=n;i++)add(S,i,1,0);
    for(int i=1;i<=n;i++)//第i个人 
    for(int j=1;j<=m;j++)//修理第j辆车 
    for(int k=1;k<=n;k++)//倒数第k个修 
    {
        add(i,j*n+k,1,a[i][j]*k);
    }
    PD(S,T);
    printf("%.2f",(double)ans/n);return 0;
 } 
原文地址:https://www.cnblogs.com/lher/p/6601975.html