给定起点终点的无向图,出发时速度为1,到达时速度也为1,在每个点可以进行速度+1,不变,-1的操作,在每条边都有限速,到达一城市后不能直接走反向边,求最短时间。
SPFA作松弛操作的典型例子,设计状态f[i][j][k]为从k城市以j速度到达城市i时的最短时间,然后开一队列依次向下一个城市做递推即可,最后看任意城市以速度1到终点城市的时间最小值即可。递推初值可设置为f[s][0][0],然后做速度必须>0的限制即可保证以速度1出发。
表示依然不太清楚struct或者class能不能直接用=赋值,重载operator =不会写,保险起见,本程序中写了assign()函数进行赋值。
// Problem#: 7692
// Submission#: 1966931
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct data{
int city,vel,back;
}s[1000000];
struct data1{
int city,d,c,next;
}a[1000];
double f[40][110][40];
int inqueue[40][110][40];
int first[40];
int tot;
void assign(struct data &a,struct data b)
{
a.city=b.city;
a.vel=b.vel;
a.back=b.back;
}
void init()
{
int i,j,k;
tot=0;
for (i=0;i<=30;i++)
for (j=0;j<=110;j++)
for (k=0;k<=30;k++)
f[i][j][k]=10000;
memset(first,0,sizeof(first));
memset(a,0,sizeof(a));
memset(inqueue,0,sizeof(inqueue));
}
void addedge(int x,int y,int d,int c)
{
tot++;
a[tot].city=y;
a[tot].d=d;
a[tot].c=c;
a[tot].next=first[x];
first[x]=tot;
tot++;
a[tot].city=x;
a[tot].d=d;
a[tot].c=c;
a[tot].next=first[y];
first[y]=tot;
}
void spfa(int s1,int g)
{
struct data now,next;
f[s1][0][0]=0;
inqueue[s1][0][0]=1;
now.city=s1;
now.vel=0;
now.back=0;
int head=0,tail=0;
assign(s[0],now);
inqueue[s1][0][0]=1;
while (head<=tail)
{
assign(now,s[head]);
for (int i=first[now.city];i;i=a[i].next)
{
if (a[i].city!=now.back)
for (int j=-1;j<=1;j++)
if (now.vel+j>0 && now.vel+j<=a[i].c && f[a[i].city][now.vel+j][now.city]>f[now.city][now.vel][now.back]+(double)a[i].d/(now.vel+j))
{
f[a[i].city][now.vel+j][now.city]=f[now.city][now.vel][now.back]+(double)a[i].d/(now.vel+j);
if (!inqueue[a[i].city][now.vel+j][now.city])
{
inqueue[a[i].city][now.vel+j][now.city]=1;
next.city=a[i].city;
next.vel=now.vel+j;
next.back=now.city;
tail++;
assign(s[tail],next);
}
}
}
inqueue[now.city][now.vel][now.back]=0;
head++;
}
}
int main()
{
int n,m,s,g,i,j,x,y,d,c;
while (scanf("%d %d",&n,&m),n|m)
{
init();
scanf("%d %d",&s,&g);
for (i=1;i<=m;i++)
{
scanf("%d %d %d %d",&x,&y,&d,&c);
addedge(x,y,d,c);
}
spfa(s,g);
double maxtime=10000;
for (j=0;j<=30;j++)
if (f[g][1][j]<maxtime)
maxtime=f[g][1][j];
if (s==g)
{
printf("0.00000\n");
continue;
}
if (maxtime==10000)
printf("unreachable\n");
else
printf("%.5lf\n",maxtime);
}
return 0;
}