题目大意:
见题面
思路:
将一天拆点为晚上和白天。
跑最小费用最大流。
在此放两个模板。
Code: 79ms / 3.23MB / 3.03KB C++17 O2
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL N = 8005;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct MCMF
{
struct EDGE
{
LL nxt, to, cost, flow;
} ee[N*N];
LL n, s, t;
LL cur[N], head[N], vis[N], a[N];
LL dis[N];
LL mincost = 0, maxflow = 0;
inline void AD(LL from, LL to, LL flow, LL cost)
{
ee[++cnt].nxt = head[from];
ee[cnt].to = to;
ee[cnt].cost = cost;
ee[cnt].flow = flow;
head[from] = cnt;
}
LL cnt = 1;
inline void add_edge(LL u, LL v, LL flow, LL cost)
{
AD(u, v, flow, cost);
AD(v, u, 0, -cost);
}
inline LL spfa()
{
for (LL i = 1; i <= n; ++i)
dis[i] = INF;
queue<LL> q;
q.push(s);
dis[s] = 0;
vis[s] = 1;
while (!q.empty())
{
LL u = q.front();
vis[u] = 0;
q.pop();
for (LL i = head[u]; i; i = ee[i].nxt)
{
LL v = ee[i].to;
if (!ee[i].flow)
continue;
if (ee[i].flow && dis[v] > dis[u] + ee[i].cost)
{
dis[v] = dis[u] + ee[i].cost;
if (!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
return dis[t] != INF;
}
inline LL dfs(LL u, LL flow)
{
if (u == t)
return flow;
LL rest = flow;
vis[u] = 1;
for (LL i = cur[u]; i && rest; i = ee[i].nxt)
{
cur[u] = i;
LL v = ee[i].to;
LL w = ee[i].cost, flow = ee[i].flow;
if (ee[i].flow && (dis[v] == dis[u] + w) && !vis[v])
{
LL k = dfs(v, min(flow, rest));
if (k)
{
maxflow += w;
mincost += k * w;
ee[i].flow -= k;
ee[i ^ 1].flow += k;
rest -= k;
}
}
}
vis[u] = 0;
return flow - rest;
}
void gkd()
{
while (spfa())
{
for (LL i = 1; i <= n; ++i)
cur[i] = head[i];
dfs(s, INF);
}
}
void init(LL nn, LL ss, LL tt)
{
n = nn, s = ss, t = tt;
for (LL i = 0; i <= n; i++)
head[i] = 0;
}
} mc;
int main()
{
LL n, m, s, t;
cin >> n;
s = 2 * n + 1; //源点不要0-index(从0开始
t = 2 * n + 2;
mc.init(2 * n + 2, s, t);
for (LL i = 1; i <= n; i++) {
LL x; cin >> x;
mc.add_edge(s, i, x, 0);
mc.add_edge(i + n, t, x, 0);
}
LL p, t1, c1, t2, c2; cin >> p >> t1 >> c1 >> t2 >> c2;
for (LL i = 1; i <= n; i++) {
if (i + 1 <= n) mc.add_edge(i, i + 1, INF, 0);
if (i + t1 <= n) mc.add_edge(i, i + n + t1, INF, c1);
if (i + t2 <= n) mc.add_edge(i, i + n + t2, INF, c2);
mc.add_edge(s, i + n, INF, p);
}
mc.gkd();
cout << mc.mincost << endl;
return 0;
}
Code: 1.47s / 2.97MB / 2.05KB C++17 O2
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL N = 8010;
struct node
{
LL v, flow, cost, next;
}edge[N*N];
LL head[N], dis[N], vis[N], pre[N], rec[N], cnt;
queue<LL> q;
inline void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
}
inline void add_edge(LL u, LL v, LL f, LL c)
{
edge[cnt].v = v; edge[cnt].flow = f; edge[cnt].cost = c;
edge[cnt].next = head[u]; head[u] = cnt++;
edge[cnt].v = u; edge[cnt].flow = 0; edge[cnt].cost = -c;
edge[cnt].next = head[v]; head[v] = cnt++;
}
LL SPFA(LL s, LL t)
{
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
while(!q.empty()) q.pop();
q.push(s); dis[s] = 0; vis[s] = 1;
while(!q.empty())
{
LL tp = q.front(); q.pop();
vis[tp] = 0;
LL k = head[tp];
while(k != -1)
{
if(dis[edge[k].v] > dis[tp] + edge[k].cost && edge[k].flow)
{
dis[edge[k].v] = dis[tp] + edge[k].cost;
pre[edge[k].v] = tp; rec[edge[k].v] = k;
if(vis[edge[k].v] == 0)
{
vis[edge[k].v] = 1;
q.push(edge[k].v);
}
}
k = edge[k].next;
}
}
if(dis[t] == INF) return 0;
return 1;
}
pair<LL, LL> Mcmf(LL s, LL t)
{
LL minflow, k, mincost = 0, maxflow = 0;
while(SPFA(s, t))
{
k = t; minflow = INF;
while(k != s)
{
minflow = min(minflow, edge[rec[k]].flow);
k = pre[k];
}
k = t; maxflow += minflow;
while(k != s)
{
mincost += minflow*edge[rec[k]].cost;
edge[rec[k]].flow -= minflow;
edge[rec[k]^1].flow += minflow;
k = pre[k];
}
}
return make_pair(maxflow, mincost);
}
int main()
{
init(); // do not forget it
LL n, m, s, t;
cin >> n;
s = 0;
t = 2 * n + 1;
for (LL i = 1; i <= n; i++) {
LL x; cin >> x;
add_edge(s, i, x, 0);
add_edge(i + n, t, x, 0);
}
LL p, t1, c1, t2, c2; cin >> p >> t1 >> c1 >> t2 >> c2;
for (LL i = 1; i <= n; i++) {
if (i + 1 <= n) add_edge(i, i + 1, INF, 0);
if (i + t1 <= n) add_edge(i, i + n + t1, INF, c1);
if (i + t2 <= n) add_edge(i, i + n + t2, INF, c2);
add_edge(s, i + n, INF, p);
}
pair<LL, LL> ans = Mcmf(s, t);
cout << ans.second << endl;
return 0;
}