您的位置:首页 > 其它

UVa11613 - Acme Corporation(不定流量的费用流)

2017-10-13 10:17 218 查看
题目链接

简介:

生产一种产品,每个月有最大销量,销售单价,最大产量,生产成本,储存期限,储存也需要一定花费,求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
,tot;
int dis
,cnt
,pre
,M,I,s,t;
bool in
;

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\n",cas,-doit(s,t));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: