LGP13271 [NOI 2025] 机器人 学习笔记
LGP13271 [NOI 2025] 机器人 学习笔记
前言
原来是国赛的签到啊,不知道的还以为是喜爱死皮的踢四呢。
题意简述
给定一个 \(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;
}
浙公网安备 33010602011771号