第2题 速度限制(speed.pas)
【问题描述】
在这个繁忙的社会中,我们往往不再去选择最短的道路,而是选择最快的路线。开车时每条道路的限速成为最关键的问题。不幸的是,有一些限速的标志丢失了,因此你无法得知应该开多快。一种可以辩解的解决方案是,按照原来的速度行驶。你的任务是计算两地间的最快路线。
你将获得一份现代化城市的道路交通信息。为了使问题简化,地图只包括路口和道路。每条道路是有向的,只连接了两条道路,并且最多只有一块限速标志,位于路的起点。两地A和B,最多只有一条道路从A连接到B。你可以假设加速能够在瞬间完成并且不会有交通堵塞等情况影响你。当然,你的车速不能超过当前的速度限制。
【输入】
输入文件speed.in的第一行是3个整数N,M和D(2<=N<=150),表示道路的数目,用0..N-1标记。M是道路的总数,D表示你的目的地。接下来的M行,每行描述一条道路,每行有4个整数A(0≤A<N),B(0≤B<N),V(0≤V≤500)and L(1≤L≤500),这条路是从A到B的,速度限制是V,长度为L。如果V是0,表示这条路的限速未知。如果V不为0,则经过该路的时间T=L/V。否则T=L/Vold,Vold是你到达该路口前的速度。开始时你位于0点,并且速度为70。
【输出】
输出文件speed.out仅一行整数,表示从0到D经过的城市。
输出的顺序必须按照你经过这些城市的顺序,以0开始,以D结束。仅有一条最快路线。
【样例】
speed.in speed.out
6 15 1 0 5 2 3 1
0 1 25 68
0 2 30 50
0 5 0 101
1 2 70 77
1 3 35 42
2 0 0 22
2 1 40 86
2 3 0 23
2 4 45 40
3 1 64 14
3 5 0 23
4 1 95 8
5 1 0 84
5 2 90 64
5 3 36 40
这道题是和以前WZZ讲过的一道题方法一样的一道题,SPFA+拆点,记得那道题是可以加速多少次的问题,一直没有做出来,这次终于是实现了。
这道题要松弛一个点,光知道两点边的权值是不行的,速度是未知的,而从不同点到线段的源点,速度是不一样的,于是在原来的dist的基础上,
需要多加一维,附加一个上一个点的信息。注意,记录方案时也需要增加一维,一开始我就错在了这里。
#include <cstdio>
#include <queue>
#include <cstdlib>
#include <cstring>
struct node
{
long a;
long b;
long v;
long l;
node* next;
};
struct pos
{
long i;
long f;
long sudu;
pos(long ii,long ff,long ss):i(ii),f(ff),sudu(ss){}
};
std::queue<pos> que;
long n;long m;long destination;
node* head[160];
double d[160][160];
bool hash[160][160];
long fa[160][160];
void spfa()
{
for (long i=0;i<n+1;i++)
for (long j=0;j<n+1;j++)
d[i][j] = 0x7fff0000;
hash[0][0] = true;
d[0][0] = 0;
que.push(pos(0,0,70));
while (!que.empty())
{
pos uu = que.front();
long u = uu.i;
que.pop();
hash[uu.f][u] = false;
for (node* vv=head[uu.i];vv;vv=vv->next)
{
long sudu = vv->v;
if (vv->v <= 0) sudu = uu.sudu;
long v = vv -> b;
if (d[u][v]>d[uu.f][u]+double(vv->l)/double(sudu))
{
fa[u][v] = uu.f;
d[u][v] = d[uu.f][u]+double(vv->l)/double(sudu);
if (!hash[u][v])
{
hash[u][v] = true;
que.push(pos(v,u,sudu));
}
}
}
}
}
void output(long u,long v)
{
if (u==v&&v==0)
{
printf("0 ");
return;
}
output(fa[u][v],u);
printf("%ld ",v);
}
void insert(long a,long b,long v,long l)
{
node* nn = new node;
nn->a = a;
nn->b = b;
nn->v = v;
nn->l = l;
nn->next = head[a];
head[a] = nn;
}
int main()
{
freopen("speed.in","r",stdin);
freopen("speed.out","w",stdout);
scanf("%ld%ld%ld",&n,&m,&destination);
for (long i=1;i<m+1;i++)
{
long a;long b;long v;long l;
scanf("%ld%ld%ld%ld",&a,&b,&v,&l);
insert(a,b,v,l);
}
spfa();
double min = 0x7fff0000;
long ans = 0;
for (long i=0;i<n+1;i++)
{
if (min > d[i][destination])
{
ans = i;
min = d[i][destination];
}
}
output(ans,destination);
return 0;
}