SYSU每周一赛(13.03.16)1003
给定起点终点的无向图,出发时速度为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; }