#include #include #include #include #include #include #include using namespace std; #define NFLAT_MAX 100 #define UNDEF (-1) #define UNREACHABLE (-2) #define INFTY INT_MAX class Slope { public: int head, length, effort; Slope( int head, int length, int adspeed ) : head(head), length(length) { // 60 より出せるときは 60 で押さえておくのがベスト. // それ以外の場合はできるだけ 70 に近づくように出し切るべき. // e の計算しきより明かである. if ( adspeed > 60 ) effort = length*10; else effort = length*(70-adspeed); } }; int nflat, nslope; int source, dest; vector G[NFLAT_MAX+1]; bool visiting[NFLAT_MAX+1]; // Longest Down Path, Smallest Effort Down Path. int LDP[NFLAT_MAX+1], SEDP[NFLAT_MAX+1]; void recTable( int n ) { // YES: There are no cycles. assert( !visiting[n] ); if ( LDP[n] != UNDEF ) return; visiting[n] = true; for ( int i = 0; i < G[n].size(); i++ ) { const Slope &e = G[n][i]; recTable(e.head); if ( LDP[e.head] == UNREACHABLE ) continue; LDP[n] = max(LDP[n], LDP[e.head]+e.length); SEDP[n] = min(SEDP[n], SEDP[e.head]+e.effort); } visiting[n] = false; if ( LDP[n] == UNDEF ) LDP[n] = UNREACHABLE; } void computeTable( int source, int dest ) { for ( int n = 1; n <= nflat; n++ ) LDP[n] = UNDEF, SEDP[n] = INFTY, visiting[n] = false; LDP[dest] = 0, SEDP[dest] = 0; recTable(source); } bool isBetter( long long n, long long d, long long N, long long D ) { if ( N == INFTY || n == 0 ) return true; return (n*D < N*d); } void compute( int u, int dest, int N, int D, int &optN, int &optD ) { if ( u == dest ) { if ( isBetter(N, D, optN, optD) ) optN = N, optD = D; return; } // pruning. それ以降の経路に現れる最大の分母和と最小の分子和を加えた // 場合が実現可能な最善であることを利用. if ( !isBetter(N+SEDP[u], D+LDP[u], optN, optD) ) return; for ( int i = 0; i < G[u].size(); i++ ) { const Slope &e = G[u][i]; if ( LDP[e.head] == UNREACHABLE ) continue; compute(e.head, dest, N+e.effort, D+e.length, optN, optD); } } int main() { ifstream cin("ski.txt"); int ntest; cin >> ntest; for ( int nt = 0; nt < ntest; nt++ ) { cin >> nflat >> nslope; cin >> source >> dest; for ( int n = 1; n <= nflat; n++ ) G[n].clear(); for ( int n = 0; n < nslope; n++ ) { int tail, head, adspeed, length; cin >> tail >> head >> adspeed >> length; G[tail].push_back(Slope(head, length, adspeed)); } computeTable(source, dest); int optN = INFTY, optD = 1; compute(source, dest, 0, 0, optN, optD); printf("%.2lf\n", (double)optN/optD); } return 0; }