LGP13271 [NOI 2025] 机器人 学习笔记

LGP13271 [NOI 2025] 机器人 学习笔记

Luogu Link

前言

原来是国赛的签到啊,不知道的还以为是喜爱死皮的踢四呢。

题意简述

给定一个 \(n\)\(m\) 边的有向图,所有结点的出边都被编上了 \(1\sim out_u\) 的编号。

一个机器人从 \(1\) 开始行动,它有一个初始为 \(1\) 的参数 \(p\)。它可以花费 \(v_p\) 的费用将 \(p\) 加一,也可以花费 \(w_p\) 的费用将 \(p\) 减一。它只能走编号与它参数相同的边。问这种情形下走到每个结点分别的最小代价。

\(1\le n,m\le 3\times 10^5\)\(1\le k\le 2.5\times 10^5\)

做法解析

拆点。一个点显然可以拆成 \(out_u\) 个点。

有一种情况是从 \(u\) 的第 \(k\) 条边走到了 \(v\),但 \(out_v\) 小于 \(k\)。如果不以 \(v\) 为终点那参数至少还要调回 \(out_v\),如果以 \(v\) 为终点就不需要额外操作。所以对于每个 \(u\) 额外拆出一个点表示接受了来自 \(out_u\ge k>out_v\) 的答案的情况。

差不多就是这样了。不需要我教你迪杰斯特拉怎么写吧。

代码实现

#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
const int MaxK=2.5e5+5,MaxN=3e5+5;
const lolo Inf=1e18;
int Tpn,N,M,K,ncnt,P[MaxN];
lolo V[MaxK],W[MaxK],wsum[MaxK],X,Y;
vector<int> vmp[MaxN];
priority_queue<pli,vector<pli>,greater<pli> > pq;
lolo dis[MaxN<<2],ans[MaxN];
struct edge{lolo v,w;};
vector<edge> Gr1[MaxN],Gr2[MaxN<<2];
void dijkstra(){
    fill(dis+1,dis+ncnt+1,Inf);
    int bgp=vmp[1][1];
    pq.push({0,bgp}),dis[bgp]=0;
    while(pq.size()){
        auto [d,u]=pq.top();pq.pop();
        if(d>dis[u])continue;
        for(auto [v,w] : Gr2[u]){
            if(dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                pq.push({dis[v],v});
            }
        }
    }
}
int main(){
    readis(Tpn,N,M,K);
    for(int i=1;i<K;i++)readi(V[i]);
    for(int i=2;i<=K;i++)readi(W[i]),wsum[i]=wsum[i-1]+W[i];
    for(int i=1;i<=N;i++){
        readi(P[i]);Gr1[i].push_back({0,0});
        for(int j=1;j<=P[i];j++)readis(X,Y),Gr1[i].push_back({X,Y});
    }
    for(int i=1;i<=N;i++)for(int j=0;j<=P[i];j++)vmp[i].push_back(++ncnt);
    for(int i=1;i<=N;i++){
        assert(vmp[i].size()==P[i]+1);
        for(int j=1;j<P[i];j++)Gr2[vmp[i][j]].push_back({vmp[i][j+1],V[j]});
        for(int j=P[i];j>1;j--)Gr2[vmp[i][j]].push_back({vmp[i][j-1],W[j]});
        for(int j=1;j<=P[i];j++){
            auto [pv,pw]=Gr1[i][j];vector<int> &uu=vmp[i],&vv=vmp[pv];
            if(P[pv]>=j)Gr2[uu[j]].push_back({vv[j],pw});
            else Gr2[uu[j]].push_back({vv[0],pw}),Gr2[uu[j]].push_back({vv[P[pv]],pw+wsum[j]-wsum[P[pv]]});
        }
    }
    dijkstra();
    for(int i=1;i<=N;i++){
        ans[i]=Inf;
        for(int j=0;j<=P[i];j++)minner(ans[i],dis[vmp[i][j]]);
        if(ans[i]==Inf)ans[i]=-1;
    }
    for(int i=1;i<=N;i++)writip(ans[i]);
    return 0;
}
posted @ 2025-07-21 08:27  矞龙OrinLoong  阅读(9)  评论(0)    收藏  举报