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

来源:互联网 发布:软件测试性能指标 编辑:程序博客网 时间:2024/05/21 22:38
题目: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;}/*12 22 10 3 20 210 100 7 5 2*/


0 0
原创粉丝点击