CF2115E Gellyfish and Mayflower 题解

Description

May 是 Gellyfish 的朋友,她非常喜欢玩一款名为《Inscryption》的游戏,这是一款在有向无环图(DAG)上进行的游戏,该图包含 nn 个顶点和 mm 条边。所有的边 aba \to b 都满足 a<ba < b

你从顶点 1 出发,携带一些金币。你需要沿着有向边从顶点 1 移动到最终 Boss 所在的顶点,并在那里与 Boss 战斗。

图中的每个顶点 ii 上都有一位商人(Trader),他会用 cic_i 枚金币出售一张攻击力为 wiw_i 的卡牌。你可以从每位商人那里购买任意数量的卡牌,但前提是你当前处在该商人所在的顶点 ii

为了打败最终 Boss,你希望你手中卡牌的总攻击力尽可能大。

你将需要回答 qq 个查询:

每个查询给定两个整数 pprr。表示最终 Boss 位于顶点 pp,你一开始有 rr 枚金币。请问,当你与最终 Boss 战斗时,你最多能拥有多少总攻击力的卡牌?注意,你可以在顶点 pp 进行交易。

n200,n1m2000,1ci200,1wi,r109n\leq 200,n-1\leq m\leq 2000,1\leq c_i\leq 200,1\leq w_i,r\leq 10^9

Solution

定义一个点的性价比 ki=wicik_i=\frac{w_i}{c_i},那么如果已知从 11 走到目标位置 pp 的路径后,除了这条路径上性价比最大的点 ii,其余总共只会选不超过 cic_i 个物品。

这是因为如果选了超过 cic_i 个物品,根据抽屉原理,一定存在一个子集的价格之和是 cic_i 的倍数,由于 ii 的性价比最高,所以把这些物品替换成 ii 一定最优。

于是只要询问的 rmaxci2r\leq\max c_i^2 就跑暴力,否则性价比不是最大的怎么选,最优解一定不会超过 rr

考虑枚举路径上性价比最高的物品,设 fs,i,rf_{s,i,r} 表示从 11 走到 ii,钦定性价比最大的是 ss,所有modci\bmod c_irr 的体积 SS 中,除去性价比最高的物品,能够选到的最大收益和减去 Scsws\left\lfloor\frac{S}{c_s}\right\rfloor\cdot w_s 的最大值。

转移这个就考虑 (s,i,r)(s,i,r)(s,i,(r+ci)modcs)\left(s,i,(r+c_i)\bmod c_s\right) 连权值为 wir+cicswsw_i-\left\lfloor\frac{r+c_i}{c_s}\right\rfloor\cdot w_s 的边,这是个同余最短路的标准形式,由于已经钦定了 ss 是性价比最高的物品了,所以这个东西没有负环。

询问时,就枚举 ss,答案为 maxi=0cs1(fs,p,i[rmodcs<i]ws+rcsws)\displaystyle\max_{i=0}^{c_s-1}{\left(f_{s,p,i}-[r\bmod c_s<i]\cdot w_s+\left\lfloor\frac{r}{c_s}\right\rfloor\cdot w_s\right)} 的最大值,直接做是 O(ncq)O(ncq) 的,用类似转两圈的东西再优化一下就可以做到 O(nq)O(nq)

时间复杂度:O(nmc+nq)O(nmc+nq)

Code

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <bits/stdc++.h>

#define int int64_t

const int kMaxN = 205;

int n, m, q, lim = 40000;
int c[kMaxN], w[kMaxN], f[kMaxN][kMaxN][kMaxN], g[kMaxN][kMaxN * kMaxN];
std::vector<int> G[kMaxN];

void chkmax(int &x, int y) { x = (x > y ? x : y); }
void chkmin(int &x, int y) { x = (x < y ? x : y); }

void dickdreamer() {
std::cin >> n >> m;
for (int i = 1; i <= n; ++i) std::cin >> c[i] >> w[i];
for (int i = 1; i <= m; ++i) {
int u, v;
std::cin >> u >> v;
G[v].emplace_back(u);
}
for (int s = 1; s <= n; ++s) {
for (int i = 1; i <= n; ++i) std::fill_n(f[s][i], c[s], -1e18);
if (1ll * w[1] * c[s] > 1ll * w[s] * c[1]) continue;
f[s][1][0] = 0;
for (int i = 1; i <= n; ++i) {
if (1ll * w[i] * c[s] > 1ll * w[s] * c[i]) continue;
for (auto j : G[i]) {
if (i > s && j < s) continue;
for (int r = 0; r < c[s]; ++r)
chkmax(f[s][i][r], f[s][j][r]);
}
for (int j = 0; j < std::__gcd(c[s], c[i]); ++j) {
for (int r = j, cc = 0; cc < 2; cc += ((r = (r + c[i]) % c[s]) == j)) {
int p = (r + c[i]) % c[s];
chkmax(f[s][i][p], f[s][i][r] + w[i] - (r + c[i]) / c[s] * w[s]);
}
}
for (int r = 0, cc = 0; cc < 2; cc += ((r = (r + 1) % c[s]) == 0)) {
int p = (r + 1) % c[s];
chkmax(f[s][i][p], f[s][i][r] - (r + 1) / c[s] * w[s]);
}
}
}
for (int i = 1; i <= n; ++i) {
for (auto j : G[i]) {
for (int k = 0; k <= lim; ++k)
chkmax(g[i][k], g[j][k]);
}
for (int j = c[i]; j <= lim; ++j)
chkmax(g[i][j], g[i][j - c[i]] + w[i]);
}
std::cin >> q;
for (int cs = 1; cs <= q; ++cs) {
int p, r;
std::cin >> p >> r;
if (r <= lim) {
std::cout << g[p][r] << '\n';
} else {
int ans = 0;
for (int s = 1; s <= p; ++s) {
chkmax(ans, f[s][p][r % c[s]] + (r / c[s]) * w[s]);
}
std::cout << ans << '\n';
}
}
}

int32_t main() {
#ifdef ORZXKR
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int T = 1;
// std::cin >> T;
while (T--) dickdreamer();
// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
return 0;
}

CF2115E Gellyfish and Mayflower 题解
https://sobaliuziao.github.io/2025/07/23/post/cdb6bcda.html
作者
Egg_laying_master
发布于
2025年7月23日
许可协议