题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2879

题意:有n道菜,每道菜需要b[i]份,m个厨师,第j个厨师做第i道菜需要时间a[i][j],求做完所有菜,所有人等待的最小总时间。

思路:设所有的菜为sum。一个明显的思路是将每个厨师拆成sum个点。然后sum个菜每个菜向每个厨师的每个点连边,表示该道菜为该厨师第几个做。由于这样数据太大。动态加边。每次增光一次后找到此次增广的厨师,每道菜将其连边。

struct node
{
    int u,v,next,cost,cap;
};

node edges[N*5];
int head[N],e;

void add(int u,int v,int cap,int cost)
{
    e++;
    edges[e].u=u;
    edges[e].v=v;
    edges[e].cap=cap;
    edges[e].cost=cost;
    edges[e].next=head[u];
    head[u]=e;
}

void Add(int u,int v,int cap,int cost)
{
    add(u,v,cap,cost);
    add(v,u,0,-cost);
}

int pre[N],F[N],C[N],visit[N];

int SPFA(int s,int t,int n)
{
    int i;
    for(i=0;i<=n;i++) F[i]=0,C[i]=INF,visit[i]=0;
    queue<int> Q;
    Q.push(s); F[s]=INF; C[s]=0;
    int u,v,cost,cap;
    while(!Q.empty())
    {
        u=Q.front();
        Q.pop();

        visit[u]=0;
        for(i=head[u];i;i=edges[i].next)
        {
            if(edges[i].cap>0)
            {
                v=edges[i].v;
                cost=edges[i].cost;
                cap=edges[i].cap;
                if(C[v]>C[u]+cost)
                {
                    C[v]=C[u]+cost;
                    F[v]=min(F[u],cap);
                    pre[v]=i;
                    if(!visit[v]) visit[v]=1,Q.push(v);
                }
            }
        }
    }
    return F[t];
}

int s,t,n,m,a[55][105],b[105],cnt[105],last[105];

int main()
{
    RD(n,m);
    int sum=0,i,j,x;
    FOR1(i,n) RD(b[i]),sum+=b[i];
    e=1;
    s=0; t=n+m+sum+1;
    FOR1(i,n)
    {
        Add(s,i,b[i],0);
        FOR1(j,m)
        {
            RD(a[i][j]);
            Add(i,n+j,1,a[i][j]);
        }
    }
    FOR1(i,m)
    {
        cnt[i]=1;
        Add(n+i,t,1,0);
        last[i]=e;
    }
    int ans=0,temp;
    while(sum--)
    {
        temp=SPFA(s,t,t);
        for(i=t;i!=s;i=edges[pre[i]].u)
        {
            x=pre[i];
            ans+=temp*edges[x].cost;
            edges[x].cap-=temp;
            edges[x^1].cap+=temp;
        }
        for(j=1;j<=m&&edges[last[j]-1].cap;j++);
        cnt[j]++;
        FOR1(i,n) Add(i,n+m+sum,1,a[i][j]*cnt[j]);
        Add(n+m+sum,t,1,0);
        last[j]=e;
    }
    PR(ans);
}

最新文章

  1. bzoj4337: BJOI2015 树的同构
  2. 新一波makefile
  3. HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效。
  4. Genymotion无法启动Virtual Box
  5. Google图片搜索
  6. poj 1328贪心
  7. 由lib引发的血案(opencv找不函数问题)
  8. apple
  9. C# - InnerList
  10. Cache基础知识OR1200在ICache一个简短的引论
  11. Mongodb 抛出异常:dbexit: really exiting now
  12. 线段树 poj 3468
  13. AngularJS数据双向绑定
  14. Hue上的Oozie构建工作流和定时任务步骤
  15. JS执行环境,作用域链及非块状作用域
  16. JS面向对象之创建对象模式
  17. 【12c】12c RMAN新特性之通过网络远程恢复数据库(RESTORE/Recover from Service)
  18. Eclipse Java注释模板设置详解以及版权声明
  19. Linux c —— opendir函数和readdir函数内涵及用法(转)
  20. H3C系列之三层交换机dhcp功能的开启

热门文章

  1. 夺命雷公狗---DEDECMS----16dedecms取出首页今日更新
  2. 手机端js事件支持(event)
  3. 解决PHP在IE浏览器下载文件,中文文件名乱码问题
  4. Office 2007在安装过程中出错-解决办法
  5. UIActionSheet和UIAlert
  6. android 中 listview 设置自动匹配高度
  7. javascript,jquery代码规范
  8. 图示-Centos7完整安装
  9. 15、Jdbc的优化(BeanUtils组件)
  10. POJ 2192 :Zipper(DP)