CF1801D/P13534 The way home/回家的路
Problem
著名魔术师博里斯·布迪尼在 X 国旅行,这个国家共有 \(n\) 个城市。不幸的是,他在编号为 \(1\) 的城市遭遇了盗窃。现在,布迪尼需要踏上回家的旅程,目标是回到编号为 \(n\) 的城市。
他打算乘坐飞机返家。全国共有 \(m\) 个航班,第 \(i\) 个航班从城市 \(a_i\) 飞往城市 \(b_i\),票价为 \(s_i\) 卢布。要搭乘某个航班,布迪尼必须身处起点城市 \(a_i\),并且手中至少有 \(s_i\) 卢布(这些钱在登机时会被扣除)。
被盗后,他仅剩 \(p\) 卢布。但他并未气馁!在任意城市 \(i\),他都可以随时举办魔术表演,每场表演能赚 \(w_i\) 卢布。
请帮助布迪尼判断,他是否能够回到家乡。如果可以,求出他至少需要举办多少场表演。
其中\(n\le 800,1\le s_i,w_i,p\le 10^9\)
Solve
这个问题有点类似于最短路,但是代价的计算更为复杂
不难发现,给定情况(余额、位置、下一步目的地),可以直接算出代价,换句话说,不同边之间的代价计算互不干扰,是独立的
既然这样,可以参照Dijkstra的底层原理,先找最优点,再去松弛
具体实现在代码中,写一个Dij,再照这个写一个推导答案的函数solve,每次以solve的最优点跑单源最短路,计算从当前点到目标点的代价,进行松弛操作
但是要注意,solve松弛的时候不用按照边来,直接枚举所有能到达的点,因为这个代价计算中含有表演的地点(因为不同地方收入不同),这样才能使所有值得算的情况被统计
具体什么样的情况最优,一定是表演次数最少的情况下,余额最多
Code
Warning:本代码能通过CF,洛谷双倍经验需要修改输入格式
#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,n,m,p,C,a[815];
struct edgeA{
int to,w;
bool operator>(const edgeA b) const {
return w>b.w;
}
};
struct edgeB{
int to,pf,res;
bool operator>(const edgeB b) const {
if(pf!=b.pf)return pf>b.pf;
return res<b.res;
}
};
int dis[815],pf[815],res[815];
bool vis[815],vis2[815];
vector<edgeA> g[815];
inline int f(int x,int y){
if(x<0)return 0;
if(x%y==0)return x/y;
return x/y+1;
}
void dij(int st){
memset(dis,0x3f,(n+10)*sizeof(long long));
memset(vis2,0,(n+10)*sizeof(bool));
priority_queue<edgeA,vector<edgeA>,greater<edgeA> > q;
dis[st]=0;
q.push({st,0});
while(!q.empty()){
int u=q.top().to,v=q.top().w;
q.pop();
if(vis2[u])continue;
vis2[u]=true;
for(int i=0;i<g[u].size();i++){
if(!vis2[g[u][i].to]&&v+g[u][i].w<dis[g[u][i].to]){
dis[g[u][i].to]=v+g[u][i].w;
q.push({g[u][i].to,dis[g[u][i].to]});
}
}
}
}
int solve(int st){
memset(pf,0x3f,(n+10)*sizeof(long long));
memset(vis,0,(n+10)*sizeof(bool));
memset(res,0,(n+10)*sizeof(bool));
priority_queue<edgeB,vector<edgeB>,greater<edgeB> > q;
pf[st]=0,res[st]=p;
q.push({st,0,p});
while(!q.empty()){
int u=q.top().to,v=q.top().pf,w=q.top().res;
q.pop();
if(vis[u])continue;
vis[u]=true;
dij(u);
for(int i=1;i<=n;i++){
if(vis[i]||dis[i]==dis[0])continue;
edgeB tmpu={i,v+f(dis[i]-w,a[u]),w+f(dis[i]-w,a[u])*a[u]-dis[i]},tmpv={i,pf[i],res[i]};
if(tmpv>tmpu){
pf[i]=tmpu.pf,res[i]=tmpu.res;
q.push(tmpu);
}
}
}
return pf[n];
}
signed main(){
cin>>T;
while(T--){
cin>>n>>m>>p;
for(int i=1;i<=n;i++)cin>>a[i],g[i].clear();
for(int i=1,u,v,w;i<=m;i++){
cin>>u>>v>>w;
g[u].push_back({v,w});
}
dij(1);
if(dis[n]==dis[0])cout<<-1<<endl;
else cout<<solve(1)<<endl;
}
return 0;
}

浙公网安备 33010602011771号