您的位置:首页 > 其它

UVA 11613 Acme Corporation(不固定流量的最小费用流)

2014-04-20 14:49 330 查看
题目:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2660

题目大意:现在一个公司生产销售X元素。M个月,每个月都有5个东西,表示这个月的每单元生产成本、最大生产量、销售单价、当月最大销售量、这个生产的东西的最大储存时间(这个月不算)。还给你一个整数,表示每单元产品留存放一个月的代价。问你,这M个月最大收益是多少?

解题思路:左边 m 个点表示m个生产月,右边 m 个点表示 m 个销售月,再加两个点,源点和汇点。从源点连左边的m个点,cap 为 最大生产量,cost 为成本。再从右边m个点分别连边到 汇点,cap 为 最大销售量,cost 为 负的单价。然后由于第 i 个月生产的东西可以存几个月,那么就从 左边每个点,分别按照可以储存的月数往右边连边,cap 为 INF,cost 为 存放一个月的代价*存放的月数。然后很清楚,求最大收益,那么就是求整张图的最小费用流,由于并没有要求满载,那么流量就是不固定的,即不固定流量的最小费用流。

    不固定的流量的最小费用流,可以用最小费用最大流来解,只需要当 s-t 的增光路长度(即 d[ t ] )> 0 时,return 0 (即不需要再增广了)就 OK 了。

    另外,这道题 cost 会超 int ,要用 long long 。

    第一道最小费用流,建模自己YY了一点,大体是出来了,但是对费用这个概念比较模糊,完整的模型并没有抽象出来。。   最后由于 long long的原因 WA 了几发,看了人家博客,才发现原来是 long long 的关系。。 = =
代码如下:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;

const int INF = 0x0fffffff;
const int MAXN = 222;
const int MAXM = MAXN*MAXN;

typedef long long lld;

struct Edge
{
int s,t,cap,flow,cost,next;
} edge[MAXM];

int tot,head[MAXN];

void edge_init()
{
tot = 0;
memset(head,-1,sizeof(head));
}

void add_edge(int s,int t,int cap,int cost)
{
edge[tot].s = s;
edge[tot].t = t;
edge[tot].cap =cap;
edge[tot].flow = 0;
edge[tot].cost = cost;
edge[tot].next = head[s];
head[s] = tot++;

edge[tot].s = t;
edge[tot].t = s;
edge[tot].cap = 0;
edge[tot].flow = 0;
edge[tot].cost = -cost;
edge[tot].next = head[t];
head[t] = tot++;
}

struct MCMF
{
int s,t,n;
int d[MAXN],p[MAXN],a[MAXN];
bool inq[MAXN];

void init(int n)
{
this->n = n;
}

int spfa(lld& flow,lld& cost)
{
for(int i = 0;i < n;i++) d[i] = INF,inq[i] = 0;
d[s] = 0;inq[s] = 1;a[s] = INF;
queue<int> q;
q.push(s);
while(!q.empty())
{
int x = q.front();
q.pop();
inq[x] = 0;
for(int i = head[x];i != -1;i = edge[i].next)
{
int to = edge[i].t;
if(edge[i].cap > edge[i].flow && d[to] > d[x]+edge[i].cost)
{
d[to] = d[x]+edge[i].cost;
p[to] = i;
a[to] = min(a[x],edge[i].cap-edge[i].flow);
if(!inq[to])
{
q.push(to);
inq[to] = 1;
}
}
}
}
if(d[t] > 0) return 0;
flow += a[t];
cost += (lld)d[t]*a[t];
int x = t;
while(x != s)
{
edge[p[x]].flow += a[t];
edge[p[x]^1].flow -= a[t];
x = edge[p[x]].s;
}
return 1;
}

lld min_cost(int s,int t)
{
this->s = s;this->t = t;
lld flow = 0,cost = 0;
while(spfa(flow,cost));
return cost;
}
} sol;

struct Month
{
int cost,pro,price,sale,t;
void read()
{
scanf("%d%d%d%d%d",&cost,&pro,&price,&sale,&t);
}
} month[111];

int nn;
int id[3][111];

void get_id_init()
{
memset(id,0,sizeof(id));
nn = 0;
}

int get_id(int i,int j)
{
if(id[i][j]) return id[i][j];
else return id[i][j] = nn++;
}

int main()
{
int cas = 0 ;
int _;
scanf("%d",&_);
while(_--)
{
int m,c;
scanf("%d%d",&m,&c);
for(int i = 0;i < m;i++)
{
month[i].read();
}
get_id_init();
int s = get_id(0,0);
int t = get_id(0,1);
edge_init();
for(int i = 0;i < m;i++)
{
add_edge(s,get_id(1,i),month[i].pro,month[i].cost);
add_edge(get_id(1,i),get_id(2,i),month[i].pro,0);
for(int j = 1;j <= month[i].t && (i+j) < m;j++)
{
add_edge(get_id(1,i),get_id(2,i+j),month[i].pro,c*j);
}
}
for(int i = 0;i < m;i++)
add_edge(get_id(2,i),t,month[i].sale,-month[i].price);
sol.init(nn);
printf("Case %d: %lld\n",++cas,-sol.min_cost(s,t));
}
return 0;
}

/*
1
2 2
2 10 3 20 2
10 100 7 5 2

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: