2024icpc(Ⅱ)网络赛补题E

E. Escape

思路:

可以看成 Sneaker 和杀戮机器人都不能在原地停留,然后杀戮机器人有个活动范围限制。如果 Sneaker 和杀戮机器人可以在原地停留,那么 Sneaker 到达一个点肯定会尽可能早,而且时间必须比杀戮机器人到达这个点短。那么预处理一下每个点最早什么时候会被杀戮机器人到达,然后在这个基础上处理出1 ∼n 的最短路即可。

由于每个机器每个时刻都不会停。我们需要分奇数和偶数时刻,来记录它们会出现的位置。

我们把点拆分为i,i+n两个点做记录。

先预处理bfs,记录所有机器人的可达点。

再跑一遍bfs,计算从起点到终点,需要的最短路径。单组数据时间复杂度 O(n + m)。

代码:

c 复制代码
#include <bits/stdc++.h>
#define int long long
#define pii pair<int, int>
using namespace std;
const int N = 1e5 + 5;
const int mod = 998244353;
#define ll long long
const int maxn = 1000010;
#define inf 2000000000

int n, m, d;
vector<int> g[maxn];
int k;
int dis[maxn];
int pre[maxn];
int dis2[maxn];
int u, v;
bool vis[maxn];

void solve()
{
    scanf("%lld%lld%lld", &n, &m, &d);
    // init
    for (int i = 0; i <= n; ++i)
    {
        g[i].clear();
        vis[i] = vis[i + n] = 0;
        pre[i] = pre[i + n] = 0;
        dis[i] = dis[i + n] = inf;
        dis2[i] = dis2[i + n] = inf;
    }
    // build gragh
    for (int i = 1; i <= m; ++i)
    {
        scanf("%lld%lld", &u, &v);
        --u, --v; // 点下标偏移到[0,n-1]
        g[u].push_back(v);
        g[v].push_back(u);
    }
    // cal dis2.
    scanf("%lld", &k);
    queue<int> q;
    for (int i = 1; i <= k; ++i)
    {
        scanf("%lld", &u);
        --u; // 点下标偏移到[0,n-1]
        q.push(u);
        vis[u] = 1;
        dis2[u] = 0;
    }
    while (!q.empty())
    {
        u = q.front();
        q.pop();
        int f = u / n; // 偶数/奇数时刻
        int x = u % n; // 原始点
        if (dis2[u] == d)
        { // 超出范围
            continue;
        }
        for (auto v : g[x])
        {
            int y = v + n * (!f); // 下一个点
            if (!vis[y] && dis2[y] > dis2[u] + 1)
            {
                dis2[y] = dis2[u] + 1;
                q.push(y);
                vis[y] = 1;
            }
        }
    }

    // cal dis.
    for (int i = 0; i <= 2 * n; ++i)
    {
        vis[i] = 0;
    }
    pre[0] = -1; // 记录位置,便于输出答案
    dis[0] = 0;
    q.push(0);
    vis[0] = 1;
    while (!q.empty())
    { // bfs过程同上,不赘述
        u = q.front();
        q.pop();
        int f = u / n;
        int x = u % n;

        for (auto v : g[x])
        {
            int y = v + n * (!f);
            if (dis[y] <= dis[u] + 1)
            {
                continue;
            }
            if (dis[u] + 1 >= dis2[y])
            {
                continue;
            }
            dis[y] = dis[u] + 1;
            pre[y] = u;
            q.push(y);
            vis[y] = 1;
        }
    }

    if (!vis[n - 1] && !vis[2 * n - 1])
    { //
        printf("-1\n");
        return;
    }
    int ed = dis[n - 1] < dis[2 * n - 1] ? n - 1 : 2 * n - 1;
    printf("%lld\n", dis[ed]);
    vector<int> res;
    while (ed != -1)
    {
        res.push_back(ed);
        ed = pre[ed];
    }
    reverse(res.begin(), res.end());
    for (auto x : res)
    {
        // 这里 x % n 求出原始点,
        // +1是为了复位,偏移到 [1,n]
        printf("%lld ", x % n + 1);
    }
    printf("\n");
}

signed main()
{
    // std::ios::sync_with_stdio(0);
    // cin.tie(0);
    // cout.tie(0);
    int t = 1;
    scanf("%lld", &t);
    while (t--)
    {
        solve();
    }

    return 0;
}
相关推荐
望舒51317 分钟前
代码随想录day25,回溯算法part4
java·数据结构·算法·leetcode
C++ 老炮儿的技术栈33 分钟前
Qt 编写 TcpClient 程序 详细步骤
c语言·开发语言·数据库·c++·qt·算法
KYGALYX37 分钟前
逻辑回归详解
算法·机器学习·逻辑回归
铉铉这波能秀1 小时前
LeetCode Hot100数据结构背景知识之集合(Set)Python2026新版
数据结构·python·算法·leetcode·哈希算法
踢足球09291 小时前
寒假打卡:2026-2-8
数据结构·算法
IT猿手1 小时前
基于强化学习的多算子差分进化路径规划算法QSMODE的机器人路径规划问题研究,提供MATLAB代码
算法·matlab·机器人
千逐-沐风1 小时前
SMU-ACM2026冬训周报3rd
算法
铉铉这波能秀1 小时前
LeetCode Hot100数据结构背景知识之元组(Tuple)Python2026新版
数据结构·python·算法·leetcode·元组·tuple
晚霞的不甘1 小时前
Flutter for OpenHarmony 实现计算几何:Graham Scan 凸包算法的可视化演示
人工智能·算法·flutter·架构·开源·音视频
㓗冽2 小时前
60题之内难题分析
开发语言·c++·算法