UVA-11613 Acme Corporation (最大费用最大流+拆点)

题目大意:有一种商品X,其每每单位存放一个月的代价I固定。并且已知其每月的最大生产量、生产每单位的的代价、最大销售量和销售单价,还已知每个月生产的X能最多能存放的时间(以月为单位)。问只考虑前m个月,最多能获得多少利润。

题目分析:增加源点s和汇点t,将每一个月视作一个节点。建立图模型如下:将每一个节点拆成两个,即将v拆成v和v1,从s向所有的v连一条弧,容量为该月最大生产量,费用为该月的单位生产代价;然后从所有的v1出发连一条弧向t,容量为该月最大销售量,费用为销售单价的相反数;最后,从v出发向所有它能存放到的月数u对应的u1连一条弧,容量为正无穷大,费用为I*(u-v)。对该模型求最小费用最大流,显然,这里对最小费用取相反数便的最大利润。

代码如下:

# include<iostream>
# include<cstdio>
# include<cmath>
# include<string>
# include<vector>
# include<list>
# include<set>
# include<map>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

# define LL long long
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a))
# define CLL(a,b,n) fill(a,a+n,b)

const double inf=1e30;
const int INF=1<<30;
const int N=300;

struct Edge
{
    int fr,to;
    LL cap,flow,cost;
    Edge(int _fr,int _to,LL _cap,LL _flow,LL _cost):fr(_fr),to(_to),cap(_cap),flow(_flow),cost(_cost){}
};
vector<Edge>edges;
vector<int>G[N];
int p[N],inq[N],n,I;
LL a[N],d[N];

void init()
{
    edges.clear();
    REP(i,0,n) G[i].clear();
}

void addEdge(int fr,int to,LL cap,LL cost)
{
    edges.push_back(Edge(fr,to,cap,0,cost));
    edges.push_back(Edge(to,fr,0,0,-cost));
    int m=edges.size();
    G[fr].push_back(m-2);
    G[to].push_back(m-1);
}

bool BellmanFord(int s,int t,LL &flow,LL &cost)
{
    CL(inq,0);
    CLL(d,INF,n);
    d[s]=0,inq[s]=1,p[s]=0,a[s]=INF;

    queue<int>q;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        inq[u]=0;
        REP(i,0,G[u].size()){
            Edge &e=edges[G[u][i]];
            if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){
                d[e.to]=d[u]+e.cost;
                p[e.to]=G[u][i];
                a[e.to]=min(a[u],e.cap-e.flow);
                if(!inq[e.to]){
                    q.push(e.to);
                    inq[e.to]=1;
                }
            }
        }
    }
    if(d[t]>0) return false;
    flow+=(LL)a[t];
    cost+=(LL)d[t]*(LL)a[t];
    for(int u=t;u!=s;u=edges[p[u]].fr){
        edges[p[u]].flow+=a[t];
        edges[p[u]^1].flow-=a[t];
    }
    return true;
}

LL Mincost(int s,int t)
{
    LL flow=0,cost=0;
    while(BellmanFord(s,t,flow,cost));
    return cost;
}

struct X
{
    int m,n,p,s,E;
};
X x[105];

int main()
{
    int T,m,s,t,cas=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&m,&I);
        n=2*m+2;
        s=0,t=2*m+1;
        init();
        REP(i,1,m+1) scanf("%d%d%d%d%d",&x[i].m,&x[i].n,&x[i].p,&x[i].s,&x[i].E);
        REP(i,1,m+1){
            addEdge(0,2*i-1,x[i].n,x[i].m);
            addEdge(2*i,t,x[i].s,-x[i].p);
        }
        REP(i,1,m+1) REP(j,i,min(i+x[i].E,m)+1)
            addEdge(2*i-1,2*j,INF,I*(j-i));
        printf("Case %d: %lld\n",++cas,-Mincost(s,t));
    }
    return 0;
}

  

时间: 2024-10-13 04:05:10

UVA-11613 Acme Corporation (最大费用最大流+拆点)的相关文章

UVa 1658 - Admiral(最小费用最大流 + 拆点)

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4533 题意: 原文地址:https://www.cnblogs.com/hkxy125/p/9539620.html

POJ3422 Kaka&#39;s Matrix Travels(最大费用最大流 + 拆点)

题目链接:http://poj.org/problem?id=3422 题意:有一个n*n的矩阵,格子中的元素是费用,KaKa从左上角开始出发要到达右下角,但是他只能向下走或者向右走,且走过的格子赋值为0,可以走K次,问K次后KaKa能获得的最大费用是多少? 思路:首先解释一下为什么要拆点?    因为要获得最大费用,所以假设当前步选择先下走,最终得到的结果可能不是最大值,但根据题意却把走过的格子赋为0了,这就影响了最终结果.所以进行拆点,把每个点拆成两个点,入度点和出度点,本点的入度点连接着本

HDU 2686 Matrix(最大费用最大流+拆点)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 和POJ3422一样 删掉K把汇点与源点的容量改为2(因为有两个方向的选择)即可 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int ma

POJ 3422 Kaka&#39;s Matrix Travels(最大费用最大流 + 拆点)

题目链接:http://poj.org/problem?id=3422 Description On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka moves one rook from the left-upper grid to the right-bottom one, taking

POJ--3422--Kaka&#39;s Matrix Travels【最小费用最大流+拆点】

链接:http://poj.org/problem?id=3422 卡卡 题意:卡卡的矩阵之旅,有一个n*n的矩阵,卡卡要从左上角走到右下角,每次他只能往右或往下走,卡卡可以走k遍这个矩阵,每个点有一个num值,卡卡走到这里可以获得num点,一个点只能获得一次num值,问卡卡走完k遍后身上num值最大可以是多少? 思路:其实看到这题时没思路,图论书上说了建图的方式,但没有说为什么,我不解,网上搜了一下解题报告,百度了两页,我看到的博客都是写了如何建图,但没有写为什么要这么建..我觉得我真是弱渣,

POj3422 Kaka&#39;s Matrix Travels 最小费用最大流 拆点

题目链接: poj3422 题意: 有一个N X N的矩阵, 矩阵的每一小格都有且仅有一个数字v,kaka每经过一个数字就会把它捡起来并将那个数字加到sum上去. 现在kaka能通过向下或向右走的方式从 (1,1)到(n,n)  K次,问kaka能取到的最大的sum是多少. 解题思路: 题目问题可以抽象为   求多次可走重复路的最长路的最大和问题 首先想到的就应该是最小费用最大流, 而题目要求的最大和值,那么应求就是最大费用最大流, 仅仅只需要将代码中的最小路算法改为最长路算法即可 题目的条件是

hdu 4494 Teamwork 最小费用最大流

Teamwork Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4494 Description Some locations in city A has been destroyed in the fierce battle. So the government decides to send some workers to repair these location

UVA 10746 Crime Wave - The Sequel【最小费用最大流】

题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1687 题意:给你n个城市到m个海港的距离,求每个城市都有船只去的最短平均航行距离. 源点向城市建边 城市向海港 海港向汇点建边 容量为1,最后城市向海港的费用为距离 代码: #include<stdio.h> #include<iostream> #in

【BZOJ3876】【Ahoi2014】支线剧情 有下界的最小费用最大流

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43025375"); } [BZOJ2324]营救皮卡丘 这道题也是一道有下界的最小费用最大流. 我的题解地址:http://blog.csdn.net/vmurder/article/details/41378979 这道题其实就是模板题. 我的处理