【题解】Luogu P3259 [JLOI2014] 路径规划
首先计算在红绿灯 \((a,b)\) 处期望的等待时间。记 \(a+b\) 为一个周期(即先有时长为 \(a\) 的红灯,再有时长为 \(b\) 的绿灯),设我们在 \(x\) 时刻到达了这个红绿灯,那么我们需要等待的时间显然为 \(\max(a-x,0)\)。
要求出期望,就要用上面那个函数的和再除以总时长,也就是 \(\frac{a^2}{2(a+b)}\)。于是这道题就变成了一道普通的图论问题。
考虑分层图,一共建 \(k+1\) 层图,在每个红绿灯处向上一层连边。考虑答案路径,一定是从起点开始再若干个加油站加油再走到终点的过程,而加油站与加油站之间怎么走我们是不用管它的。那么我们就以每个加油站为起点跑最短路,将所有加油站抽出来,在限制内能走到另一个加油站就在新图上连边。最后再在新图上跑一次最短路即可。
时间复杂度 \(O(50kn\log kn)\)。
#include<bits/stdc++.h>
#define ll long long
#define il inline
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define id(x,y) ((x)+n*((y)-1))
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int maxn=2e5+5;
int n,m,_k,lim,cst;
double dis[maxn],out[maxn];
bool gas[maxn],vis[maxn];
map<string,int> hao;
vector<pair<int,double> > e1[maxn],e2[maxn];
priority_queue<pair<double,int> > q;
il void dijkstra(int s,auto &e){
for(int i=1;i<=n*(_k+1);i++){
dis[i]=1e18,vis[i]=0;
}
dis[s]=0,q.push(mp(0,s));
while(q.size()){
int u=q.top().sec;
q.pop();
if(vis[u]){
continue;
}
vis[u]=1;
for(auto i:e[u]){
int v=i.fir;
double w=i.sec;
if(!vis[v]&&dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push(mp(-dis[v],v));
}
}
}
}
namespace cplx{
bool end;
il double usdmem(){return (&begin-&end)/1048576.0;}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m>>_k>>lim>>cst;
for(int i=1,a,b;i<=n;i++){
string s;
cin>>s>>a>>b;
hao[s]=i;
gas[i]=~s.find("gas");
if(a){
// cout<<i<<"\n";
out[i]=a*1.0*a/2/(a+b);
}
}
int st=hao["start"],ed=hao["end"];
for(int i=1,u,v,w;i<=m;i++){
string a,b,c;
cin>>a>>b>>c>>w;
u=hao[a],v=hao[b];
for(int j=1;j<=_k+1;j++){
if(out[u]){
if(j<=_k){
e1[id(u,j)].pb(mp(id(v,j+1),w+out[u]));
}
}
else{
e1[id(u,j)].pb(mp(id(v,j),w));
}
if(out[v]){
if(j<=_k){
e1[id(v,j)].pb(mp(id(u,j+1),w+out[v]));
}
}
else{
e1[id(v,j)].pb(mp(id(u,j),w));
}
}
}
for(int i=1;i<=n;i++){
if(i==st||gas[i]){
// cout<<i<<"---";
dijkstra(i,e1);
for(int j=1;j<=n;j++){
if(gas[j]){
for(int k=1;k<=_k+1;k++){
if(dis[id(j,k)]<=lim){
for(int x=1,y=k;y<=_k+1;x++,y++){
e2[id(i,x)].pb(mp(id(j,y),dis[id(j,k)]+cst));
// cout<<id(i,x)<<" "<<id(j,y)<<" "<<dis[id(j,k)]+cst<<"\n";
}
}
}
}
else if(j==ed){
for(int k=1;k<=_k+1;k++){
if(dis[id(j,k)]<=lim){
for(int x=1,y=k;y<=_k+1;x++,y++){
e2[id(i,x)].pb(mp(id(j,y),dis[id(j,k)]));
// cout<<id(i,x)<<" "<<id(j,y)<<" "<<dis[id(j,k)]<<"\n";
}
}
}
}
}
}
}
dijkstra(st,e2);
double ans=1e18;
for(int i=1;i<=_k+1;i++){
// cout<<dis[id(ed,i)]<<"\n";
ans=min(ans,dis[id(ed,i)]);
}
printf("%.3f",ans);
return 0;
}
}
int main(){return asbt::main();}

浙公网安备 33010602011771号