当前位置: 首页 > article >正文

2024icpc(Ⅱ)网络赛补题E

E. Escape

在这里插入图片描述

思路:

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

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

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

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

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

代码:

#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;
}


http://www.kler.cn/a/325092.html

相关文章:

  • MODBUS TCP转CANOpen网关
  • 深入理解Redis(七)----Redis实现分布式锁
  • gvim添加至右键、永久修改配置、放大缩小快捷键、ctrl + c ctrl +v 直接复制粘贴、右键和还原以前版本(V)冲突
  • BERT模型中的嵌入后处理与注意力掩码
  • 3、C语言基本数据类型关键字
  • 微信小程序-prettier 格式化
  • C++(list的简单实现,着重点是迭代器)
  • navicat连接postgresql的ERROR: column datlastsysoid
  • 美图AI短片创作工具MOKI全面开放 支持生成配乐、细节修改
  • Pencils Protocol 成市场新宠,生态通证$DAPP价值几何
  • 鸿蒙HarmonyOS开发生态
  • 使用vite+react+ts+Ant Design开发后台管理项目(四)
  • 巧用枚举消除条件判断
  • ETH以太网资源学习
  • 【YashanDB知识库】yashandb执行包含带oracle dblink表的sql时性能差
  • 学习react小记
  • 独孤思维:又取关了一批副业博主,真相扎心了
  • 区块链媒体推广:15个数字解读未来-华媒舍
  • 代码随想录算法训练营day41
  • 周家庄智慧旅游小程序
  • Excel-统计日期内的个数1月到12月
  • 研究生如何利用ChatGPT帮助开展日常科研工作?
  • Linux---文件io
  • delphi制作漂亮的农历窗体(IntraWeb+Layui的完美结合)
  • 【设计模式-中介者模式】
  • EHS管理系统设备安全设施安全监控模块