题解:P13271 [NOI2025] 机器人
考虑如何建图。
首先,我们可以关注到了一个良好的条件:(废话)
于是考虑拆点,设
显然,对于一个点
1.当
2.当
3.
所以当
所以,这样建图边的数量就是
最后跑一遍
#include <bits/stdc++.h>
typedef long long ll;
const int N = 3e5 + 5;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n, m, k, s, vis[N], to[N];
ll V[N], W[N];
std::vector<std::pair<int, ll>> Q[N];
ll ans[N], dis[N];
struct Node {
ll dis; int u, p;
bool operator< (Node a) const { return dis > a.dis; }
};
std::priority_queue<Node> que;
int main()
{
std::memset(ans, 0x3f, sizeof(ans));
std::memset(dis, 0x3f, sizeof(dis));
scanf("%*d%d%d%d", &n, &m, &k); ans[1] = dis[1] = 0;
for (int i = 1; i < k; ++i) scanf("%lld", V + i), V[i] += V[i - 1];
for (int i = 2; i <= k; ++i) scanf("%lld", W + i), W[i] += W[i - 1];
for (int i = 1; i <= n; ++i) {
scanf("%d", &s);
for (int j = 1, v, w; j <= s; ++j)
scanf("%d%d", &v, &w), Q[i].emplace_back(v, w);
to[i + 1] = to[i] + s;
}
if (Q[1].empty()) { // 特判 d[1] = 0 的情况,但貌似数据没有卡这个?
printf("0");
for (int i = 2; i <= n; ++i)
printf(" -1");
return 0;
}
que.push({0, 1, 1});
while (!que.empty()) {
auto [d, u, p] = que.top(); que.pop();
if (vis[to[u] + p]) continue; vis[to[u] + p] = 1;
auto [v, w] = Q[u][p - 1]; int q = Q[v].size();
ans[v] = std::min(ans[v], dis[to[u] + p] + w);
if (q >= p) {
if (dis[to[u] + p] + w < dis[to[v] + p]) {
dis[to[v] + p] = dis[to[u] + p] + w;
if (!vis[to[v] + p]) que.push({dis[to[v] + p], v, p});
}
} else if (q) {
w += W[p] - W[q];
if (dis[to[u] + p] + w < dis[to[v] + q]) {
dis[to[v] + q] = dis[to[u] + p] + w;
if (!vis[to[v] + q]) que.push({dis[to[v] + q], v, q});
}
}
if (p < Q[u].size()) {
w = V[p] - V[p - 1]; q = p + 1;
if (dis[to[u] + p] + w < dis[to[u] + q]) {
dis[to[u] + q] = dis[to[u] + p] + w;
if (!vis[to[u] + q]) que.push({dis[to[u] + q], u, q});
}
}
if (p > 1) {
w = W[p] - W[p - 1]; q = p - 1;
if (dis[to[u] + p] + w < dis[to[u] + q]) {
dis[to[u] + q] = dis[to[u] + p] + w;
if (!vis[to[u] + q]) que.push({dis[to[u] + q], u, q});
}
}
}
for (int i = 1; i <= n; ++i)
printf("%lld ", ans[i] == INF ? -1 : ans[i]);
return 0;
}