专栏文章
题解:P13271 [NOI2025] 机器人
P13271题解参与者 5已保存评论 5
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @miouu5yn
- 此快照首次捕获于
- 2025/12/03 01:31 3 个月前
- 此快照最后确认于
- 2025/12/03 01:31 3 个月前
考虑如何建图。
首先,我们可以关注到了一个良好的条件:。(废话)
于是考虑拆点,设 表示机器人到达点 ,且 时的状态。
显然,对于一个点 ,最多向其他点连 条边。(设 )
1.当 时,,边权为 。
2.当 时,,边权为 。
3.,边权为 。这里有一个细节,当 时,我们是没有 这个点的( 太大了,而点 只有 条边)。
所以当 时,我们要将点 连向 ,边权为 。
所以,这样建图边的数量就是 级别的。
最后跑一遍 时间复杂度 。
CPP#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;
}
相关推荐
评论
共 5 条评论,欢迎与作者交流。
正在加载评论...