最短路+定积分 csu1806 Toll

传送门:点击打开链接

题意:一个有向图,但是只有10个点。然后每条路的费用会随着时间变化,费用等于ci*t+di。可以认为车在路上行驶不花费时间,所以时间只与出发时间有关。

现在问从1到n去,在[0,T]这一段时间内出发,平均费用是多少。

思路:首先我们得能看出这个积分表达式才行,萌萌哒的叉姐已经提示我们了(业界良心啊。。

然后,Simpson求定积分,如果函数连续,且可以求出给定x时的y值,那么就能用了。

很显然,给定x值时,对于这个题,就相当于告诉你出发时间,后面显然就是个傻逼最短路。

所以这题只要看懂这个套路就是个傻逼题。。555555

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int>PII;

const int MX = 1e3 + 5;
const int INF = 0x3f3f3f3f;

struct Edge {
    int v, nxt, c, d;
} E[MX];
int Head[MX], erear;
void edge_init(int n) {
    erear = 0;
    for(int i = 1; i <= n; i++) Head[i] = -1;
}
void edge_add(int u, int v, int c, int d) {
    E[erear].v = v;
    E[erear].c = c;
    E[erear].d = d;
    E[erear].nxt = Head[u];
    Head[u] = erear++;
}

int n, m, T;
double d[MX];

double f(double x) {
    typedef pair<double, int> Data;
    priority_queue<Data, vector<Data>, greater<Data> > Q;
    for(int i = 1; i <= n; i++) d[i] = INF;

    d[1] = 0; Q.push(Data(0, 1));
    while(!Q.empty()) {
        Data ftp = Q.top(); Q.pop();
        if(ftp.first != d[ftp.second]) continue;

        int u = ftp.second;
        for(int i = Head[u]; ~i; i = E[i].nxt) {
            int v = E[i].v;
            double cost = x * E[i].c + E[i].d;
            if(d[u] + cost < d[v]) {
                d[v] = d[u] + cost;
                Q.push(Data(d[v], v));
            }
        }
    }
    return d[n];
}
double simpson(double a, double b) {
    double c = a + (b - a) / 2;
    return (f(a) + 4 * f(c) + f(b)) * (b - a) / 6;
}
double asr(double a, double b, double eps, double A) {
    double c = a + (b - a) / 2;
    double L = simpson(a, c), R = simpson(c, b);
    if(fabs(L + R - A) <= 15 * eps) return L + R + (L + R - A) / 15.0;
    return asr(a, c, eps / 2, L) + asr(c, b, eps / 2, R);
}
double asr(double a, double b, double eps) {
    return asr(a, b, eps, simpson(a, b));
}

int main() {
    // FIN;
    while(~scanf("%d%d%d", &n, &m, &T)) {
        edge_init(n);
        for(int i = 1; i <= m; i++) {
            int u, v, c, d;
            scanf("%d%d%d%d", &u, &v, &c, &d);
            edge_add(u, v, c, d);
        }
        printf("%f\n", asr(0, T, 1e-6) / T);
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值