BZOJ 2424: [HAOI2010]订货 费用流

2424: [HAOI2010]订货

Time Limit: 1 Sec

Memory Limit: 256 MB

题目连接

http://www.lydsy.com/JudgeOnline/problem.php?id=2424

Description

某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费。假设仓库容量为S。

Input

第1行:n, m, S (0<=n<=50, 0<=m<=10, 0<=S<=10000)

第2行:U1 , U2 , ... , Ui , ... , Un (0<=Ui<=10000)

第3行:d1 , d2 , ..., di , ... , dn (0<=di<=100)

Output

只有1行,一个整数,代表最低成本

Sample Input

3 1 1000
2 4 8
1 2 4

Sample Output

34

HINT

题意

题解:

费用流,S--月--T

|

      下个月

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int MAXN = 10000;
const int MAXM = 100000;
const int INF = 0x3f3f3f3f;
struct Edge
{
    int to, next, cap, flow, cost;
    int x, y;
} edge[MAXM],HH[MAXN],MM[MAXN];
int head[MAXN],tol;
int pre[MAXN],dis[MAXN];
bool vis[MAXN];
int N, M;
char map[MAXN][MAXN];
void init()
{
    N = MAXN;
    tol = 0;
    memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int cap, int cost)//左端点,右端点,容量,花费
{
    edge[tol]. to = v;
    edge[tol]. cap = cap;
    edge[tol]. cost = cost;
    edge[tol]. flow = 0;
    edge[tol]. next = head[u];
    head[u] = tol++;
    edge[tol]. to = u;
    edge[tol]. cap = 0;
    edge[tol]. cost = -cost;
    edge[tol]. flow = 0;
    edge[tol]. next = head[v];
    head[v] = tol++;
}
bool spfa(int s, int t)
{
    queue<int>q;
    for(int i = 0; i < N; i++)
    {
        dis[i] = INF;
        vis[i] = false;
        pre[i] = -1;
    }
    dis[s] = 0;
    vis[s] = true;
    q.push(s);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int i = head[u]; i != -1; i = edge[i]. next)
        {
            int v = edge[i]. to;
            if(edge[i]. cap > edge[i]. flow &&
                    dis[v] > dis[u] + edge[i]. cost )
            {
                dis[v] = dis[u] + edge[i]. cost;
                pre[v] = i;
                if(!vis[v])
                {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    if(pre[t] == -1) return false;
    else return true;
}
//返回的是最大流, cost存的是最小费用
int minCostMaxflow(int s, int t, int &cost)
{
    int flow = 0;
    cost = 0;
    while(spfa(s,t))
    {
        int Min = INF;
        for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
        {
            if(Min > edge[i]. cap - edge[i]. flow)
                Min = edge[i]. cap - edge[i]. flow;
        }
        for(int i = pre[t]; i != -1; i = pre[edge[i^1]. to])
        {
            edge[i]. flow += Min;
            edge[i^1]. flow -= Min;
            cost += edge[i]. cost * Min;
        }
        flow += Min;
    }
    return flow;
}

int main()
{
    int n, m, ss;
    scanf("%d%d%d",&n,&m,&ss);
    int ch = 0, cm = 0;
    init();//注意
    int beg = 0;//超级起点
    int end = 3000;//超级汇点
    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        addedge(i,end,x,0);
    }
    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        addedge(0,i,9999999,x);
    }
    for(int i=1;i<n;i++)addedge(i,i+1,ss,m);
    int ans = 0;
    minCostMaxflow(beg,end,ans);
    printf("%d\n",ans);
}
时间: 2024-10-27 07:05:42

BZOJ 2424: [HAOI2010]订货 费用流的相关文章

BZOJ 2424: [HAOI2010]订货(最小费用最大流)

最小费用最大流..乱搞即可 ------------------------------------------------------------------------------ #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<queue> #define rep( i, n ) for( int i = 0; i <

bzoj2424: [HAOI2010]订货(费用流)

2424: [HAOI2010]订货 题目:传送门 题解: 做多了最小割,做一下费用流练手 其实很容易就看出来是费用流啊,伏地魔肉老师用单调队列ORZ st直接连每个月,流量无限(随便买,花钱而已),费用就是给出来的 然后因为可以贮存嘛,那就第i个月连第i+1个月,流量为S(仓库容量),费用为m就OK 最后就是卖出去咯,第i个月连ed流量为需要的,费用为0 难受,打个spfa忘记出队列... 代码: 1 #include<cstdio> 2 #include<cstring> 3

bzoj:2424: [HAOI2010]订货

Description 某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费.假设仓库容量为S. Input 第1行:n, m, S (0<=n<=50, 0<=m<=10, 0<=S<=10000) 第2行:U1 , U2

BZOJ 2661 连连看(费用流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2661 题意:给出一个区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y)的平方差x^2-y^2是一个完全平方数z^2,并且y与z互质,那么就可以将x和y一起消除,同时得到x+y点分数.要求就是,消除的数对尽可能多的前提下,得到的分数尽量多. 思路:首先暴力出所有合法的数对(x,y).然后将每个用到的数字拆成两个点,每个数对连一条边.最后的答案除以2即可. struct nod

BZOJ 2879 美食节(费用流-动态加边)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2879 题意:有n道菜,每道菜需要b[i]份,m个厨师,第j个厨师做第i道菜需要时间a[i][j],求做完所有菜,所有人等待的最小总时间. 思路:设所有的菜为sum.一个明显的思路是将每个厨师拆成sum个点.然后sum个菜每个菜向每个厨师的每个点连边,表示该道菜为该厨师第几个做.由于这样数据太大.动态加边.每次增光一次后找到此次增广的厨师,每道菜将其连边. struct node { i

BZOJ 2597 WC2007 剪刀石头布 费用流

题目大意:给出一张竞赛图中的其中几条单向边,剩下的边随意定向.问最多可以形成多少三元环. 思路:对于任意三个点来说,他们组成了三元环,当且仅当这些点的入度=处度 = 1.如果没有组成三元环,只需要改变这其中任意一条边的方向,使得一个点的入度变成2,一个点的出度变成2.我们只需要算出有多少三个点中有一个点的入度为2的就可以了,并最小化这个东西. 通过公式:ans=C(n,3)-ΣC(degree[x],2)可以发现,我们只需要让每个点的入度尽可能小.由此想到费用流模型(我怎么想不到..) 类似于x

BZOJ 1927 星际竞速(费用流)

考虑费用流,题目要求走n个点都走完且恰好一次,显然流量的限制为n. 建立源点s和汇点t,并把每个星球拆成两个点i和i',分别表示已到达该点和经过该点. 对于能力爆发,建边(s,i',1,w). 对应高速航行,建边(s,i,1,0), (i,j',1,w). 因为每个点必须走一次且只能走一次.建边(i',t,1,0). 其实就是类似最小路径覆盖的建图方法. # include <cstdio> # include <cstring> # include <cstdlib>

BZOJ SCOI 2007 修车 费用流

题目大意:有一些车和一些修车的人,给出每个人修每个车的时间,问所有人等待的最短平均时间是多少. 思路:记得POJ有一个和这个很像的题,做法是一样的.对于每个人修车的时候,我们只考虑他修车的时间对在它之后修车的人的时间的影响,因此我们只要考虑每一辆车是倒数第几个修的就可以了,然后朴素的建图,跑朴素的费用流,就可以过. CODE: #include <queue> #include <cstdio> #include <cstring> #include <ioman

BZOJ 3442 学习小组 费用流

题目大意:给出学生的数目和学习小组的数目,学生参加小组需要交纳费用,每个小组会支出C[i]*cnt[i]^2.每个学生可以参加k个小组,问最多的学生参加时,最小支出费用. 思路:如果不算后面那个什么鬼的条件的话,见图十分显然. S->每个学生 f:k,c:0 每个学生->每个学习小组 f:1,c:-F[i] 每个学习小组->T f:1,c:1 * C[i],3 * C[i],5 * C[i],7 * C[i],...... 后面的条件其实是说,每个学生的k次机会不一定全用光,但是所有人都