toj 4611 Repairing a Road

来源:互联网 发布:mac 磁盘工具找回照片 编辑:程序博客网 时间:2024/05/29 12:33

toj 4611 Repairing a Road


时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte
总提交: 49 测试通过:19

描述

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.

输入

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 xi, yi (1<=xi, yi<=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.

输出

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 2
1 2 1.5 1.8
2 3 2.0 1.5
2 1
1 2 2.0 1.8
0 0

样例输出

2.589
1.976

#include <iostream>#include <cstdio>#include <algorithm>#include <queue>#include <cmath>using namespace std;const double INFD = (1 << 30) + 0.1;const double eps = 1e-6;const int MAX_VERTEX = 100 + 5;// 邻接矩阵,cost数组,存储两点间最短路double cost[MAX_VERTEX][MAX_VERTEX];// 顶点数,边数int C, R;struct edge {    // 起点,终点    int stat, ed;    // 权值,一个因子    double v, a;};// 存放边的信息,用于在修路之后,更新最短距离queue<edge> edges;// 1 -> C的最短路长度double ans;// 初始化队列和邻接矩阵void init() {    while(!edges.empty()) {        edges.pop();    }    for (int i = 1; i <= C; i++) {        for (int j = 1; j <= C; j++) {            if (i == j) {                cost[i][j] = 0;            } else {                cost[i][j] = INFD;            }        }    }}// floyd算法求两点间的最短路径void floyd() {    for (int k = 1; k <= C; k++) {        for (int i = 1; i <= C; i++) {            for (int j = 1; j <= C; j++) {                cost[i][j] = min(cost[i][j], cost[i][k] + cost[k][j]);            }        }    }}// 修一条路更新最短路求1->C的最短距离void update() {    while (!edges.empty()) {        edge e = edges.front();        edges.pop();        // 记录从1到该边始点的最短时间        double time = 0;        // 已知v*a^(-t)        // 如果a无限接近0的话,t的最小值为0        // 否则按如下公式计算        if (abs(e.a - 1) > eps) {            // 公式计算过程            // y = t + v*a^(-t) => y' = 1 + (-v*a^(-t)ln(a)) = 0            // => a^t = v*ln(a) => t = log(a, v*ln(a))            // => t = ln(v*ln(a))/ln(a)            time = log(e.v * log(e.a)) / log(e.a);        }        // 取1->e.stat这条路径的最短距离        time = max(time, cost[1][e.stat]);        // ans = min(min(1->e.stat) + f(e.stat, t.to) + min(e.ed->N))        ans = min(ans, time + e.v * pow(e.a, -time) + cost[e.ed][C]);    }}int main() {    while (scanf("%d%d", &C, &R) == 2 && (C || R)) {        // 初始化        init();        // 输入并加入边队列        // input();        for (int i = 0; i < R; i++) {            edge e;            scanf("%d%d%lf%lf", &e.stat, &e.ed, &e.v, &e.a);            // 无向图            cost[e.stat][e.ed] = e.v;            cost[e.ed][e.stat] = e.v;            edges.push(e);            swap(e.stat, e.ed);            edges.push(e);        }        // 求出未修路的最短距离        floyd();        ans = cost[1][C];        update();        //solve();        printf("%.3lf\n", ans);    }    return 0;}
0 0
原创粉丝点击