枚举每条边,那么耗费时间就是dis(1, x) + (t - dis(1, x)) + vi * ai ^ (-t) + dis(y, C) ,dis代表u到v的最短路,可知因为是最短路,1到u和v到c肯定不会经过(u,v)这条边,所以求出t-vi*ai^(-t)的最小值就可以了,t的范围(dis(1,x),dis(1,c))
求导求零点就行了,f'(t) = 1 - ln(ai) * vi * ai ^ (-t)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <set>
#include <queue>
using namespace std;
const int INF=1e9+10;
const double EPS = 1e-10;
typedef long long ll;
double mp[105][105];
struct t{
int x,y;
double v,a;
t(){};
t(int xx,int yy,double vv,double aa){x=xx;y=yy;v=vv;a=aa;};
}edge[105];
double erfen(double l,double r,double a,double v){
for(int i=0;i<10;i++){
double mid=(l+r)/2.0;
if(1.0-1.0*log(a)*v*pow(a,-mid)<0) l=mid;
else r=mid;
}
return l+v*pow(a,-l);
}
int main(){
//freopen("out.txt","w",stdout);
int c,r;
while(scanf("%d %d",&c,&r)&&c&&r){
for(int i=0;i<=c;i++)
for(int j=0;j<=c;j++)
if(i!=j)
mp[i][j]=INF;
else mp[i][j]=0.0;
for(int i=0;i<r;i++){
int x,y;
double v,a;
scanf("%d %d %lf %lf",&x,&y,&v,&a);
mp[x][y]=mp[y][x]=v;
edge[i]=t(x,y,v,a);
}
for(int k=1;k<=c;k++)
for(int i=1;i<=c;i++)
for(int j=1;j<=c;j++)
mp[i][j]=min(mp[i][j],mp[i][k]+mp[j][k]);
//f'(t) = 1 - ln(ai) * vi * ai ^ (-t)
double ans=mp[1][c];
for(int i=0;i<r;i++){
ans=min(ans,mp[edge[i].x][c]+erfen(mp[1][edge[i].y],ans,edge[i].a,edge[i].v));
ans=min(ans,mp[edge[i].y][c]+erfen(mp[1][edge[i].x],ans,edge[i].a,edge[i].v));
}
printf("%.3f\n",ans );
}
return 0;
}