题目大意:精明的小R每每开车出行总是喜欢走最快路线,而不是最短路线.很明显,每条道路的限速是小R需要考虑的关键问题.不过有一些限速标志丢失了,于是小R将不知道能开多快.不过有一个合理的方法是进入这段道路时不改变速度行驶.你的任务就是计算从小R家(0号路口)到D号路口的最快路线.
现在你得到了这个城市的地图,这个地图上的路都是单向的,而且对于两个路口A和B,最多只有一条道路从A到B.并且假设可以瞬间完成路口的转弯和加速.
BZOJ的source已经暴露了一切…直接上spfa,对于一个点记录到达它时的速度,然后进行转移,基本上就是一个分层图的思路吧。因为要输出方案,多开一个数组记录就行了。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int maxn=150+10;
const int maxv=500+10;
int inq[maxn][maxv],n,m,d,out[maxn],tot;
double dis[maxn][maxv];
struct edge
{
int to,v,l;
};
struct node
{
int p,v;
}go[maxn][maxv];
vector<edge> g[maxn];
queue<node> Q;
int main()
{
//freopen("3245.in","r",stdin);
//freopen("3245.out","w",stdout);
scanf("%d%d%d",&n,&m,&d);d++;
for(int i=1;i<=m;i++)
{
int a,b,v,l;
scanf("%d%d%d%d",&a,&b,&v,&l);a++;b++;
g[a].push_back((edge){b,v,l});
}
for(int i=0;i<=n;i++) for(int j=0;j<=500;j++) dis[i][j]=1000000000;
dis[1][70]=0;inq[1][70]=0;Q.push((node){1,70});
while(!Q.empty())
{
node x=Q.front();Q.pop();inq[x.p][x.v]=0;
for(int i=0;i<g[x.p].size();i++)
{
edge e=g[x.p][i];int np=e.to,nv=e.v;
if(!nv) nv=x.v;double cc=(double)e.l/(double)nv;
if(dis[np][nv]>dis[x.p][x.v]+cc)
{
dis[np][nv]=dis[x.p][x.v]+cc;
go[np][nv]=(node){x.p,x.v};
if(!inq[np][nv])
{
inq[np][nv]=1;
Q.push((node){np,nv});
}
}
}
}
double ans=1000000000.00;int hp=d,hv;
for(int i=1;i<=500;i++)
if(dis[d][i]<ans)
{
ans=dis[d][i];
hv=i;
}
//cout<<ans<<endl;
while(go[hp][hv].p)
{
out[++tot]=go[hp][hv].p;
int tp=hp,tv=hv;
hp=go[tp][tv].p;hv=go[tp][tv].v;
}
for(int i=tot;i;i--) printf("%d ",out[i]-1);
printf("%d\n",d-1);
return 0;
}