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;
}
相关推荐
源代码•宸几秒前
分布式缓存-GO(分布式算法之一致性哈希、缓存对外服务化)
开发语言·经验分享·分布式·后端·算法·缓存·golang
yongui4783439 分钟前
MATLAB的指纹识别系统实现
算法
高山上有一只小老虎41 分钟前
翻之矩阵中的行
java·算法
jghhh011 小时前
RINEX文件进行卫星导航解算
算法
爱思德学术1 小时前
中国计算机学会(CCF)推荐学术会议-A(计算机科学理论):LICS 2026
算法·计算机理论·计算机逻辑
CVHub1 小时前
多模态图文训推一体化平台 X-AnyLabeling 3.0 版本正式发布!首次支持远程模型推理服务,并新增 Qwen3-VL 等多款主流模型及诸多功能特性,等
算法
hoiii1871 小时前
MATLAB实现Canny边缘检测算法
算法·计算机视觉·matlab
qq_430855882 小时前
线代第二章矩阵第四课:方阵的幂
算法·机器学习·矩阵
roman_日积跬步-终至千里2 小时前
【计算机设计与算法-习题2】动态规划应用:矩阵乘法与钢条切割问题
算法·矩阵·动态规划
kupeThinkPoem2 小时前
计算机算法导论第三版算法视频讲解
数据结构·算法