抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

LOJ 6079

题解

\(n\le 1000\),还要输出方案,容易想到网络流。首先我们假设每个时刻都选 S,记 \(a_i=s_i-e_i\),那么问题变成了调整若干个时刻 \(j\),对于每个长度为 \(k\) 的区间,调整的时刻数量 \(x\) 应该满足 \(me\le x\le k-ms\),在这个前提下,使得 \(a_j\) 之和尽量小。

考虑这样一个建模方法:源点 \(S\) 向某个点 \(P\)\((k-ms,0)\) 的边(\((x,y)\) 表示流量上界为 \(x\),费用为 \(y\) 的边,下同),点 \(P\)\([1,k]\) 的点连 \((\infty,0)\) 的边,点 \(i\)\(i+1\)\((k-ms-me,0)\) 的边,\(i\)\(i+k\)\((1,a_i)\) 的边(\(i+1,i+k>n\) 时则向汇点 \(T\) 连边)。然后跑最小费用最大流的结果就是答案。

考虑这样建模为什么是对的。显然流只会从编号小的点流向编号大的点。我们假设从小到大处理每一个点 \(i\),处理过的点已经满足流量平衡,未处理的点则把入流先“屯”着。有入流的点说明这个点需要调整。对于当前要处理的点 \(i\),我们发现这个点“屯”着的流量就是 \([i,i+k-1]\) 这个区间中还能放的点数,已经有入流的点属于已经确定的点。由于总流量是 \(k-ms\),而每个长度为 \(k\) 的区间只考虑 \(i\)\(i+1\) 的边只能流出 \(k-ms-me\) 的流量,所以一定会有至少 \(me\) 个点被调整。(这一段是我自己yy的)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <vector>
int read(){
register int x = 0;
register char f = 1, ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f ^= 1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ '0');
return f ? x : -x;
}
struct Graph{
const static int N = 2005, M = 10005, INF = 0x3f3f3f3f;
int S, T, edge, to[M], pr[M], cap[M], cost[M], hd[N];
Graph(){ edge = 0, memset(hd, -1, sizeof hd); }
void addedge(int u, int v, int w, int c){
to[edge] = v, cap[edge] = w, cost[edge] = c, pr[edge] = hd[u], hd[u] = edge++;
to[edge] = u, cap[edge] = 0, cost[edge] = -c, pr[edge] = hd[v], hd[v] = edge++;
}
int h, t, Q[1000005], vis[N], mn[N], pre[N];
long long dis[N];
bool SPFA(){
memset(dis, 0x3f, sizeof dis), memset(vis, 0, sizeof vis);
h = 0, t = 1, Q[t] = S, dis[S] = 0, vis[S] = 1, pre[S] = 0, mn[S] = INF;
while (h < t){
int u = Q[++h]; vis[u] = 0;
for (register int i = hd[u], v; ~i; i = pr[i])
if (cap[i] && dis[u] + cost[i] < dis[v = to[i]]){
dis[v] = dis[u] + cost[i], mn[v] = std :: min(mn[u], cap[i]), pre[v] = i;
if (!vis[v]) Q[++t] = v, vis[v] = 1;
}
}
return dis[T] != dis[N - 1];
}
long long MinCostMaxFlow(int _S, int _T){
long long res = 0;
S = _S, T = _T;
while (SPFA()){
res += mn[T] * dis[T];
for (register int i = T; i != S; i = to[pre[i] ^ 1])
cap[pre[i]] -= mn[T], cap[pre[i] ^ 1] += mn[T];
}
return res;
}
}G;
int n, k, ms, me, a[1005], E[1005];
long long sum;
int main(){
n = read(), k = read(), ms = read(), me = read();
for (register int i = 1; i <= n; ++i) a[i] = read(), sum += a[i];
for (register int i = 1; i <= n; ++i) a[i] -= read();
for (register int i = 1; i <= n; ++i){
G.addedge(i, i + 1, k - ms - me, 0);
E[i] = G.edge;
G.addedge(i, std :: min(i + k, n + 1), 1, a[i]);
}
for (register int i = 1; i <= k; ++i) G.addedge(0, i, Graph :: INF, 0);
G.addedge(n + 2, 0, k - ms, 0);
printf("%lld\n", sum - G.MinCostMaxFlow(n + 2, n + 1));
for (register int i = 1; i <= n; ++i)
if (G.cap[E[i]]) putchar('S'); else putchar('E');
}

评论