E-Rush Hour 2
题目大意是:有n个城市,从城市a到城市b会花费c + d /( t +1 )的时间,且0点的时候不允许通行,问能不能从城市1到城市n,能就输出花费的最小时间,不能输出 -1
这个题写的时候很容易想到优先队列的迪杰斯特拉,但是对这个图的存储需要花费一点小心思,需要保留一个最适合出发的时间,这个时间可以从给的公式t + = c + d /( t +1
得到,根据高中的知识(a + b > =2 * sqrt( a * b)),可以得知,当t = sqrt (d)-1 时,是最适合出发的时间 ,根据这个最适合的时间来判断并更新时间的位置,小于最适合的时间,就等到最适合的时间,大于就直接走
迪杰斯特拉用到了链式前向星,不会的可以看看我这篇博客
贴上代码
#include<stdio.h>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<math.h>
#include<string.h>
#define ll long long
using namespace std;
typedef pair<ll,ll> pii;
const ll MAX=0x3f3f3f3f3f3f3f3f;
const ll N=1e5+10;
const ll M=2*N;
ll n,m,a,b,c2,d2,tt=MAX,gen1;
ll head[N]={0},to[M],c[M],d[M],dist[M],next1[M],vis[M]={0},cnt;
void add(ll a,ll b,ll c1,ll d1){
to[++cnt]=b;
c[cnt]=c1,d[cnt]=d1;
next1[cnt]=head[a]; //next找的是下一条可以走的路(前面已经联通过的路),线性排序每一条路
head[a]=cnt;//head[a]是此时的路
}
void djs(){
memset(dist,MAX,sizeof(dist));
dist[1]=0;
priority_queue<pii,vector<pii>,greater<pii> > q;
q.push({0,1});//first 是时间 ,second 是城市i
while(q.size()){
pii p=q.top();
q.pop();
if(vis[p.second]){
continue;
}
vis[p.second]=1;
for(ll i=head[p.second];i;i=next1[i]){ //i是此时是第几条路
ll best=MAX;
ll j=to[i];
ll x=(ll)sqrt(1.0*d[i]);
ll L=max(dist[p.second],x-10),R=x+10;
R=max(R,L);//保证l是个大于0的正数
for(ll t=L;t<=R;t++){
ll s=t+c[i]+d[i]/(t+1);
best=min(best,s);
}
if(dist[j]>best){
dist[j]=best;
q.push({best,j});
}
}
}
if(dist[n]==MAX){
printf("-1\n");
}else cout<<dist[n]<<endl;
}
int main(){
cin>>n>>m;
for(ll i=0;i<m;i++){
cin>>a>>b>>c2>>d2;
add(a,b,c2,d2);
add(b,a,c2,d2);
}
djs();
return 0;
}