2013 Asia Hangzhou Regional Contest hdu4780 Candy Factory

现场赛这题就看了一眼就再没多想了,被别的题卡住的时候就更没心思想了,比较可惜。

模型一眼就是费用流,主要是题意的理解和构图方式。


首先机器的区别只在于一开始做每个糖果的花费和时间不同,除此之外没有任何区别。

每个糖果生产完毕的时间也是确定的(Ti),所以某机器生产完一个糖果又生产另一个糖果的花费也是确定的。

所以时间的意义只在于计算费用而已啦……


构图就比较清晰了:

从源点到每个机器连边,流量1费用0。

每个糖果拆成两个点,分为入点和出点,从入点到出点连上界下界都是1费用为0的边,在把每个糖果的出点同汇点连边,流量1费用0。

对于每个机器和每个糖果的入点,计算花费连流量为1的边。

每个糖果之间也如此连边。


跑最小费用流,当下界没满足(maxflow<n)时输出-1即可。


code:

int n , m , K;
int S , T;
#define Maxn 100
int SS[Maxn] , TT[Maxn];
int C[Maxn][Maxn] , D[Maxn][Maxn] , E[Maxn][Maxn] , F[Maxn][Maxn];

void work()
{
    int i , j , x , y;
    S = n + m + n , T = S + 1 , s = T + 1 , t = s + 1;
    for (i = 0 ; i < n ; ++ i)
        scanf("%d%d",&SS[i] , &TT[i]);
    for (i = 0 ; i < n ; ++ i)
        for (j = 0 ; j < m ; ++ j)
            scanf("%d",&C[j][i]);
    for (i = 0 ; i < n ; ++ i)
        for (j = 0 ; j < m ; ++ j)
            scanf("%d",&D[j][i]);
    for (i = 0 ; i < n ; ++ i)
        for (j = 0 ; j < n ; ++ j)
            scanf("%d",&E[i][j]);
    for (i = 0 ; i < n ; ++ i)
        for (j = 0 ; j < n ; ++ j)
            scanf("%d",&F[i][j]);
    memset(pre , -1 , sizeof(pre)) , mcnt = 0;
    for (i = 0 ; i < n ; ++ i)
    {
        addarc(s , i << 1 | 1 , 1 , 0);
        addarc(i << 1  , t , 1 , 0);
        addarc(i << 1 | 1 , T , 1 , 0);
    }
    for (i = n + n ; i < n + n + m ; ++ i)
        addarc(S , i , 1 , 0);
    for (i = 0 ; i < m ; ++ i)
        for (j = 0 ; j < n ; ++ j)
        {
            x = i + n + n;
            if (C[i][j] <= SS[j])
                addarc(x , j << 1 , 1 , D[i][j]);
            else if (C[i][j] < TT[j])
                addarc(x , j << 1 , 1 , D[i][j] + K * (C[i][j] - SS[j]));
        }
    for (i = 0 ; i < n; ++ i)
        for (j = 0 ; j < n ; ++ j)  if (i != j)
        {
            x = TT[i] + E[i][j];
            if (x <= SS[j])
                addarc(i << 1 | 1 , j << 1 , 1 , F[i][j]);
            else if (x < TT[j])
                addarc(i << 1 | 1 , j << 1 , 1 , F[i][j] + K * (x - SS[j]));
        }
    addarc(T , S , 1 << 30 , 0);
    Mincostflow();
    if (maxflow != n)
        puts("-1");
    else printf("%d\n" , ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值