【網絡流】[HAOI2010] 訂貨

LinkLink

luoguluogu 25172517

DescriptionDescription

某公司估計市場在第i個月對某產品的需求量爲Ui,已知在第i月該產品的訂貨單價爲di,上個月月底未銷完的單位產品要付存貯費用m,假定第一月月初的庫存量爲零,第n月月底的庫存量也爲零,問如何安排這n個月訂購計劃,才能使成本最低?每月月初訂購,訂購後產品立即到貨,進庫並供應市場,於當月被售掉則不必付存貯費。假設倉庫容量爲S。

InputInput

第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)

OutputOutput

只有1行,一個整數,代表最低成本

SampleSample InputInput

3 1 1000
2 4 8
1 2 4 

SampleSample OutputOutput

34

TrainTrain ofof ThoughtThought

最小費用最大網絡流
下面講一下建圖:
建一個源點,與每一個月連接上,費用是物品單價,容量無限大,因爲可以買無限個物品
然後每個月之間可以繼承物品,費用就是貯存費用,容量是倉庫容量
最後建一個匯點,與每一個月的連接起來,費用是0(賣出不需要成本), 容量是每月需求量
然後配上最小費用最大流模板就A了

CodeCode

#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);
}
發佈了224 篇原創文章 · 獲贊 35 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章