UVa11613

题目链接

简介:
生产一种产品,每个月有最大销量,销售单价,最大产量,生产成本,储存期限,储存也需要一定花费,求M个月中的最大利润

分析:
把每一个月拆成两个点 x1,x2
源点向x1连边,流量是每个月的最大产量,费用是生产成本
x2向汇点连边,流量是每个月的最大销量,费用是销售价格的相反数
x1向x2连边,流量为INF,费用是0
x1向(x+1),(x+2),…,(x+e)的的二个点连边,流量是INF,费用就是储存花费,表示产品的储存

这样连出来的图就是一个

不定流量的最小费用流

我们直接上最小费用流,当s-t增广路长度大于0时就停止增广
注意:求最短路一定要用Bellman,因外有初始负费用

附样例图:
这里写图片描述

tip

到底能储存几个月一定要看好了
储存e个月是指x+1到x+e

答案开ll

外国网站比较lj了,和AC程序对拍:
这里写图片描述

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define ll long long

using namespace std;

const int INF=0x33333333;
const int N=210;
struct node{
    int x,y,v,c,nxt;
};
node way[N*N*2];
int st[N],tot;
int dis[N],cnt[N],pre[N],M,I,s,t;
bool in[N];

void add(int u,int w,int z,int cc)
{
    tot++;
    way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].c=cc;way[tot].nxt=st[u];st[u]=tot;
    tot++;
    way[tot].x=w;way[tot].y=u;way[tot].v=0;way[tot].c=-cc;way[tot].nxt=st[w];st[w]=tot;
}

int Bellman(int s,int t,int n)
{
    memset(cnt,0,sizeof(cnt));
    memset(in,0,sizeof(in));
    memset(pre,0,sizeof(pre));
    memset(dis,0x33,sizeof(dis));
    queue<int> Q;
    Q.push(s);
    dis[s]=0;
    in[s]=1;

    while (!Q.empty())
    {
        int now=Q.front(); Q.pop();
        in[now]=0;
        for (int i=st[now];i!=-1;i=way[i].nxt)
            if (way[i].v)
            {
                if (dis[way[i].y]>dis[now]+way[i].c)
                {
                    dis[way[i].y]=dis[now]+way[i].c;
                    pre[way[i].y]=i;
                    if (!in[way[i].y])
                    {
                        Q.push(way[i].y);
                        in[way[i].y]=1;
                        if (++cnt[way[i].y]>n) return 0;
                    }
                }
            }
    }
    return dis[t]!=INF;
}

ll doit(int s,int t)
{
    ll ans=0;
    while (Bellman(s,t,t+1)&&dis[t]<0)
    {
        int sum=INF;
        for (int i=t;i!=s;i=way[pre[i]].x)
            sum=min(sum,way[pre[i]].v);
        ans+=(ll)sum*dis[t];
        for (int i=t;i!=s;i=way[pre[i]].x)
            way[pre[i]].v-=sum,
            way[pre[i]^1].v+=sum;
    }
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    for (int cas=1;cas<=T;cas++)
    {
        memset(st,-1,sizeof(st));
        tot=-1;
        scanf("%d%d",&M,&I);
        s=0; t=2*M+1;
        int m,n,p,ss,e;
        for (int i=1;i<=M;i++)
        {
            scanf("%d%d%d%d%d",&m,&n,&p,&ss,&e);   //生产成本,最大产量,销售单价,最大销售量,储存时间 
            add(s,i,n,m);
            add(i+M,t,ss,-p);
            add(i,i+M,INF,0);
            for (int j=i+1;j<=min(i+e,M);j++)
                add(i,j+M,INF,(j-i)*I);
        }
        printf("Case %d: %lld
",cas,-doit(s,t));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wutongtong3117/p/7673042.html