【网络流】[HAOI2010] 订货

L i n k Link

l u o g u luogu 2517 2517

D e s c r i p t i o n Description

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

I n p u t 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)

O u t p u t Output

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

S a m p l e Sample I n p u t Input

3 1 1000
2 4 8
1 2 4 

S a m p l e Sample O u t p u t Output

34

T r a i n Train o f of T h o u g h t Thought

最小费用最大网络流
下面讲一下建图:
建一个源点,与每一个月连接上,费用是物品单价,容量无限大,因为可以买无限个物品
然后每个月之间可以继承物品,费用就是贮存费用,容量是仓库容量
最后建一个汇点,与每一个月的连接起来,费用是0(卖出不需要成本), 容量是每月需求量
然后配上最小费用最大流模板就A了

C o d e Code

#include<iostream>
#include<cstring> 
#include<cstdio>
#include<queue>

using namespace std;
const int inf = 1e9;

int n, m, S, t, tt, ans, s;
int u[10005], d[10005], c[10005], h[10005], dis[10005], prev[10005];

struct node
{
	int from, to, flow, val, num, next; 
}g[100005];

void add(int x, int y, int flow, int val)
{
	g[++tt] = (node) {x, y, flow, val, tt + 1, h[x]}; h[x] = tt;//正向边
	g[++tt] = (node) {y, x, 0, -val, tt - 1, h[y]}; h[y] = tt; //反向边
}

bool spfa()
{
	memset(c, 0, sizeof(c));
	queue<int>Q;
	for (int i = 0; i <= n + 1; ++i) dis[i] = inf;
	dis[s] = 0;
	c[s] = 1;
	Q.push(s);
	while (Q.size())
	{
		int x = Q.front();
		Q.pop();
		for (int i = h[x]; i; i = g[i].next)
		{
			if (g[i].flow && dis[g[i].to] > dis[x] + g[i].val)
			{
				dis[g[i].to] = dis[x] + g[i].val;
				prev[g[i].to] = i;
				if (!c[g[i].to]) {
					Q.push(g[i].to);
					c[g[i].to] = 1;
				}
			} 
		}
		c[x] = 0;
	}
	if (dis[t] == inf) return 0;
	 else return 1;
}

void mcf()
{
	int x;
	int flow_ = inf; x = t;
	while (prev[x])
	{
		flow_ = min(flow_, g[prev[x]].flow);
		x = g[prev[x]].from;
	}
	ans += flow_ * dis[t];
	x = t;
	while (prev[x])
	{
		g[prev[x]].flow -= flow_;
		g[g[prev[x]].num].flow += flow_;
		x = g[prev[x]].from;
	}
}

int main()
{
	scanf("%d%d%d", &n, &m, &S);
	for (int i = 1; i <= n; ++i)
		scanf("%d", &u[i]);
	for (int i = 1; i <= n; ++i)
		scanf("%d", &d[i]);
	s = 0; t = n + 1;
	for (int i = 1; i <= n; ++i)
		add(s, i, 1e9, d[i]);
	for (int i = 1; i < n; ++i)
		add(i, i + 1, S, m);
	for (int i = 1; i <= n; ++i)
		add(i, t, u[i], 0);
	while(spfa()) mcf();
	printf("%d", ans);
}

猜你喜欢

转载自blog.csdn.net/LTH060226/article/details/104010715