YTU 2547: Repairing a Road

2547: Repairing a Road

时间限制: 1 Sec   内存限制: 128 MB
提交: 3   解决: 2

题目描述

You live in a small town with R bidirectional roads connecting C crossings and you want to go from crossing 1 to crossing C as soon as possible. You can visit other crossings before arriving at crossing C, but it’s not mandatory.

 

You have exactly one chance to ask your friend to repair exactly one existing road, from the time you leave crossing 1. If he repairs the i-th road for t units of time, the crossing time after that would be viai-t. It's not difficult to see that it takes vi units of time to cross that road if your friend doesn’t repair it.

 

You cannot start to cross the road when your friend is repairing it.

 

Input

There will be at most 25 test cases. Each test case begins with two integers C and R (2<=C<=100, 1<=R<=500). Each of the next R lines contains two integers xiyi (1<=xiyi<=C) and two positive floating-point numbers vi and ai (1<=vi<=20,1<=ai<=5), indicating that there is a bidirectional road connecting crossing xi and yi, with parameters vi and ai (see above). Each pair of crossings can be connected by at most one road. The input is terminated by a test case with C=R=0, you should not process it.

 

Output

For each test case, print the smallest time it takes to reach crossing C from crossing 1, rounded to 3 digits after decimal point. It’s always possible to reach crossing C from crossing 1.

输入

输出

样例输入

3 21 2 1.5 1.82 3 2.0 1.52 11 2 2.0 1.80 0

样例输出

2.5891.976

迷失在幽谷中的鸟儿,独自飞翔在这偌大的天地间,却不知自己该飞往何方……

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
const int MAXN = 110;
const int MAXE = 1010;
const double EPS = 1e-6;
inline int sgn(double x)
{
    if(fabs(x) < EPS) return 0;
    return x > 0 ? 1 : -1;
}
double fpai(double t, double v, double a)
{
    return 1 - log(a) * v * pow(a, - t);
}
inline void update_min(double &a, const double &b)
{
    if(a > b) a = b;
}
double mat[MAXN][MAXN];
int x[MAXE], y[MAXE];
double v[MAXE], a[MAXE];
int n, m;
void floyd()
{
    for(int k = 1; k <= n; ++k)
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j) update_min(mat[i][j], mat[i][k] + mat[k][j]);
}
double find_t(int i, int x, int y, double l, double r)
{
    double L = l, R = r;
    while(R - L > EPS)
    {
        double mid = (L + R) / 2;
        if(fpai(mid, v[i], a[i]) > 0) R = mid;
        else L = mid;
    }
    if(sgn(fpai(L, v[i], a[i])) != 0) return l;
    return L;
}
double solve()
{
    double t, ans = mat[1][n];
    for(int i = 0; i < m; ++i)
    {
        t = find_t(i, x[i], y[i], mat[1][x[i]], ans);
        update_min(ans, t + v[i] * pow(a[i], -t) + mat[y[i]][n]);
        t = find_t(i, y[i], x[i], mat[1][y[i]], ans);
        update_min(ans, t + v[i] * pow(a[i], -t) + mat[x[i]][n]);
    }
    return ans;
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        if(n == 0 && m == 0) break;
        for(int i = 1; i <= n; ++i)
        {
            for(int j = 1; j <= n; ++j) mat[i][j] = 1e5;
            mat[i][i] = 0;
        }
        for(int i = 0; i < m; ++i)
        {
            int aa, bb;
            double cc;
            scanf("%d%d%lf%lf", &aa, &bb, &cc, &a[i]);
            x[i] = aa;
            y[i] = bb;
            v[i] = cc;
            update_min(mat[aa][bb], cc);
            update_min(mat[bb][aa], cc);
        }
        floyd();
        printf("%.3f\n", solve());
    }
}

转载于:https://www.cnblogs.com/im0qianqian/p/5989484.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值