Luogu P13271 [NOI 2025] 机器人 题解 [ 绿 ] [ 分层图最短路 ]

[NOI 2025] 机器人:奶龙题,感觉严格小于接龙。

题目显然可以转化为一共 \(k\) 层的有向图,每次跳到不同层需要花费一定的代价,求从 \(1\) 为起点的单源最短路。

显然可以建立 \(k\) 层的分层图,对应的边只在对应层建立,直接跑单源最短路即可,时间复杂度 \(O(nk\log nk)\),无法通过。

注意到每一层有很多点是无用的,于是直接动态开点,每个点只开对应度数和作为出度的层数即可,对于一次跳跃多层的路径可以前缀和预处理出每层之间跳跃的代价以快速计算。为了方便这一部分可以采用 map 实现。时间复杂度 \(O(n\log n \log k)\),用哈希表的话可以做到 \(O(n\log n)\)

#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
using pii=pair<ll,pi>;
const int N=300005;
const ll inf=0x3f3f3f3f3f3f3f3f;
int n,m,k,v[N],w[N],d[N];
ll f[N];
map<int,ll>dis[N];
map<int,bool>vis[N];
vector<pi>g[N];
priority_queue<pii,vector<pii>,greater<pii> >q;
int main()
{
    //freopen("sample.in","r",stdin);
    //freopen("sample.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int cid;
    cin>>cid>>n>>m>>k;
    for(int i=1;i<=k-1;i++)cin>>v[i];
    for(int i=2;i<=k;i++)
    {
        cin>>w[i];
        f[i]=f[i-1]+w[i];
    }
    for(int i=1;i<=n;i++)
    {
        cin>>d[i];
        g[i].push_back({0,0});
        dis[i][0]=inf;
        for(int j=1;j<=d[i];j++)
        {
            int y,z;
            cin>>y>>z;
            g[i].push_back({y,z});
            dis[i][j]=inf;
            dis[y][j]=inf;
        }
    }
    dis[1][1]=0;
    q.push({0,{1,1}});
    while(!q.empty())
    {
        pii cur=q.top();
        q.pop();
        int u=cur.se.fi,lv=cur.se.se;
        if(vis[u][lv])continue;
        vis[u][lv]=1;
        if(lv>1&&dis[u].count(lv-1)&&dis[u][lv-1]>dis[u][lv]+w[lv])
        {
            dis[u][lv-1]=dis[u][lv]+w[lv];
            q.push({dis[u][lv-1],{u,lv-1}});
        }
        if(lv<k&&dis[u].count(lv+1)&&dis[u][lv+1]>dis[u][lv]+v[lv])
        {
            dis[u][lv+1]=dis[u][lv]+v[lv];
            q.push({dis[u][lv+1],{u,lv+1}});
        }
        if(lv<g[u].size()&&dis[g[u][lv].fi][min(lv,d[g[u][lv].fi])]>dis[u][lv]+g[u][lv].se+f[lv]-f[min(lv,d[g[u][lv].fi])])
        {
            dis[g[u][lv].fi][min(lv,d[g[u][lv].fi])]=dis[u][lv]+g[u][lv].se+f[lv]-f[min(lv,d[g[u][lv].fi])];
            q.push({dis[u][lv]+g[u][lv].se+f[lv]-f[min(lv,d[g[u][lv].fi])],{g[u][lv].fi,min(lv,d[g[u][lv].fi])}});
        }
        if(lv<g[u].size()&&dis[g[u][lv].fi][lv]>dis[u][lv]+g[u][lv].se)
        {
            dis[g[u][lv].fi][lv]=dis[u][lv]+g[u][lv].se;
            q.push({dis[g[u][lv].fi][lv],{g[u][lv].fi,lv}});
        }
    }
    for(int i=1;i<=n;i++)
    {
        ll res=inf;
        for(auto itm:dis[i])
        {
            res=min(res,itm.se);
        }
        if(res==inf)cout<<-1<<" ";
        else cout<<res<<" ";
    }
    return 0;
}
posted @ 2025-07-14 17:40  KS_Fszha  阅读(165)  评论(0)    收藏  举报