题意:

给你n个要修的车,m个人

问你修完他们的总时间/n等于几

题解:

最小费用最大流

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

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

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

最小费用最大流即可

代码:

#include<bits/stdc++.h>
#define inf 0x7fffffff
#define T 601
using namespace std;
int n,m,cnt=1,ans,t[61][10];
int d[605],q[605],from[605],head[605];
bool mark[605];
struct edge{int from,to,next,c,v;}e[100001];
void ins(int u,int v,int w,int c)
{
    cnt++;
    e[cnt].from=u;e[cnt].to=v;
    e[cnt].next=head[u];head[u]=cnt;
    e[cnt].c=c;e[cnt].v=w;
}
void jb(int u,int v,int w,int c){ins(u,v,w,c);ins(v,u,0,-c);}
bool spfa()
{
    memset(mark,0,sizeof(mark));
    for (int i=0;i<=T;i++)d[i]=inf;
    int t=0,w=1;
    d[T]=0;mark[T]=1;q[0]=T;
    while (t!=w)
     {
        int now=q[t];t++;
        if(t==T)t=0;
        for (int i=head[now];i;i=e[i].next)
         if (e[i^1].v&&d[e[i].to]>d[now]-e[i].c)
          {
            d[e[i].to]=d[now]-e[i].c;
            if (!mark[e[i].to])
             {
                 mark[e[i].to]=1;
                q[w++]=e[i].to;
                if(w==T)w=0;
             } 
          }
        mark[now]=0;    
     }
    if (d[0]==inf)return 0;
    return 1;
}
int dfs(int x,int f)
{
    if(x==T){mark[T]=1;return f;}
    int used=0,w;
    mark[x]=1;
    for (int i=head[x];i;i=e[i].next)
     if (!mark[e[i].to]&&e[i].v&&d[x]-e[i].c==d[e[i].to])
      {
        w=f-used;
        w=dfs(e[i].to,min(e[i].v,w));
        ans+=w*e[i].c;
        e[i].v-=w;e[i^1].v+=w;
        used+=w;
        if (used==f)return f;
      }
    return used;
}
void zkw()
{
    while(spfa())
    {
        mark[T]=1;
        while(mark[T])
        {
            memset(mark,0,sizeof(mark));
            dfs(0,inf);
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
     for (int j=1;j<=n;j++)scanf("%d",&t[i][j]);
    for (int i=1;i<=n*m;i++)jb(0,i,1,0);
    for (int i=n*m+1;i<=n*m+m;i++)jb(i,T,1,0);
    for (int i=1;i<=n;i++)
     for (int j=1;j<=m;j++)
      for (int k=1;k<=m;k++)jb((i-1)*m+j,n*m+k,1,t[k][i]*j);
    zkw();
    printf("%.2lf",(double)ans/m);
    return 0;
}

 

posted on 2018-02-14 09:57  宣毅鸣  阅读(111)  评论(0编辑  收藏  举报