题目大意:A公司生产一种元素,给出该元素在未来M个月中每个月的单位售价,最大生产量,生产成本,最大销售量和最大存储时间,和每月存储代价,问这家公司在M个月内所能赚大的最大利润
解题思路:这题建图还是比较简单的。主要说一下怎么跑出答案吧。我用的是MCMF,建边的时候,费用我用的是相反数,所以得到最小费用后要去相反数
MCMF的时候,用一个数组纪录了到达汇点时所花费的最小价值,因为取的是相反数,所以当价值为正时,就表示已经亏本了,所以可以退出了
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define N 1010
#define ll long long
#define abs(a)((a)>0?(a):(-(a)))
#define INF 0x3f3f3f3f3f3f3f3f
struct Edge{
int from, to;
ll cap, flow ,cost;
Edge() {}
Edge(int from, int to, ll cap, ll flow, ll cost):from(from), to(to), cap(cap), flow(flow), cost(cost) {}
};
struct MCMF{
int n, m, source, sink;
vector<Edge> edges;
vector<int> G[N];
ll d[N], f[N];
int p[N];
bool vis[N];
void init(int n) {
this->n = n;
for (int i = 0; i <= n; i++)
G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, ll cap, ll cost) {
edges.push_back(Edge(from, to, cap, 0, cost));
edges.push_back(Edge(to, from, 0, 0, -cost));
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool BellmanFord(int s, int t, ll &flow, ll &cost) {
for (int i = 0; i <= n; i++)
d[i] = INF;
memset(vis, 0, sizeof(vis));
vis[s] = 1; d[s] = 0; f[s] = INF; p[s] = 0;
queue<int> Q;
Q.push(s);
while (!Q.empty()) {
int u = Q.front();
Q.pop();
vis[u] = 0;
for (int i = 0; i < G[u].size(); i++) {
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];
f[e.to] = min(f[u], e.cap - e.flow);
if (!vis[e.to]) {
vis[e.to] = true;
Q.push(e.to);
}
}
}
}
if (d[t] > 0)
return false;
flow += f[t];
cost += d[t] * f[t];
int u = t;
while (u != s) {
edges[p[u]].flow += f[t];
edges[p[u] ^ 1].flow -= f[t];
u = edges[p[u]].from;
}
return true;
}
ll Mincost(int s, int t) {
ll flow = 0, cost = 0;
while (BellmanFord(s, t, flow, cost));
return cost;
}
};
MCMF mcmf;
int n, m, source, sink, cas = 1;
struct Node{
ll m, n, p, s, e;
}node[N];
void init() {
scanf("%d%d", &n, &m);
source = 0; sink = 2 * n + 1;
mcmf.init(sink);
for (int i = 1; i <= n; i++) {
scanf("%lld%lld%lld%lld%lld", &node[i].m, &node[i].n, &node[i].p, &node[i].s, &node[i].e);
mcmf.AddEdge(source, i, node[i].n, 0);
mcmf.AddEdge(i + n, sink, node[i].s, 0);
}
for (int i = 1; i <= n; i++) {
mcmf.AddEdge(i, i + n, INF, node[i].m - node[i].p);
for (int j = 1; j <= node[i].e && i + j <= n; j++)
mcmf.AddEdge(i, i + j + n, INF, m * j + node[i].m - node[i+j].p);
}
ll ans = mcmf.Mincost(source, sink);
printf("Case %d: %lld\n", cas++, abs(ans));
}
int main() {
int test;
scanf("%d", &test);
while (test--) {
init();
}
return 0;
}