题解:P13271 [NOI2025] 机器人
更新
这是一篇已通过的题解。
思路
首先看到的是
所以每个点有两个状态:第
转移共分为两种:
- 同一个点内转移,即
i 不变,p 变。 - 不同点间转移,即
i 变,p 不变。
这样太麻烦了,不如每次转移
变
变后的
变
有个例外,我们也可以只变
每次转移的花费为非负整数,可以使用 dijkstra 求最短路。
最后对每个点,统计
时间复杂度为
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,pii> plii;
const int MAXN=3e5+3;
const ll Inf=1e18;
int n,m,k,d[MAXN];
vector<pii>edg[MAXN];
vector<ll>dis[MAXN];
vector<bool>vis[MAXN];
priority_queue<plii>q;
ll sumv[MAXN],sumw[MAXN];
ll gs(int x,int y){
if(x<y)return sumv[y-1]-sumv[x-1];
else return sumw[x]-sumw[y];
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int c; cin>>c>>n>>m>>k;
for(int i=1;i<k;i++){
cin>>sumv[i];
sumv[i]+=sumv[i-1];
}
for(int i=2;i<=k;i++){
cin>>sumw[i];
sumw[i]+=sumw[i-1];
}
for(int i=1;i<=n;i++){
cin>>d[i];
vis[i].assign(d[i]+1,0);
dis[i].assign(d[i]+1,Inf);
edg[i].assign(d[i]+1,{0,0});
for(int j=1;j<=d[i];j++){
int y,z; cin>>y>>z;
edg[i][j]={y,z};
}
}
for(int i=1;i<=d[1];i++){
dis[1][i]=gs(1,i);
q.push({-dis[1][i],{1,i}});
}
while(!q.empty()){
pii pos=q.top().second; q.pop();
int fr=pos.first,p=pos.second;
if(vis[fr][p])continue;
vis[fr][p]=1;
int to=edg[fr][p].first;
ll cost0=dis[fr][p]+edg[fr][p].second;
dis[to][0]=min(dis[to][0],cost0);
for(int i=1;i<=d[to];i++){
ll cost=cost0+gs(p,i);
if(cost<dis[to][i]){
dis[to][i]=cost;
q.push({-cost,{to,i}});
}
}
}
for(int i=1;i<=n;i++){
sort(dis[i].begin(),dis[i].end());
cout<<(dis[i][0]==Inf?-1:dis[i][0])<<' ';
}
return 0;
}