CSU 1806 (simpson積分 最短路)

題目鏈接:點擊這裏

題意:n個點m條有向邊的圖,每條邊的花費是cit+bi ,設f(t) 表示給定t的時候1-n的最小花費,求這裏寫圖片描述

因爲對於給定的t,f(t) 就是1-n的花費最短路。所以直接套simpson積分,積分函數的結果就是當前t時的最短路。

#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-9;
#define INF 1e15
#define maxn 15
#define maxm 205

struct node {
    int next, c, d, v;
}edge[maxm];
int head[maxn], cnt;
int n, m, T;
double d[maxn];

void add_edge (int u, int v, int a, int b) {
    node &e = edge[cnt];
    e.v = v, e.c = a, e.d = b, e.next = head[u], head[u] = cnt++;
}

bool vis[maxn];
int top, num[maxn];
void spfa (int start, int n, double x) {
    memset (vis, 0, sizeof vis);
    for (int i = 1; i <= n; i++) {
        d[i] = INF;
    }
    vis[start] = 1;
    d[start] = 0;
    queue <int> q;
    while (!q.empty ()) q.pop ();
    q.push (start);
    memset (num, 0, sizeof num);
    num[start] = 1;
    while (!q.empty ()) {
        int u = q.front (); q.pop ();
        vis[u] = 0;
        for (int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].v;
            if (d[v]>d[u]+edge[i].c*x+edge[i].d) {
                d[v] = d[u]+edge[i].c*x+edge[i].d;
                if (!vis[v]) {
                    vis[v] = 1;
                    q.push (v);
                }
            }
        }
    }
}

double F (double x) {
    spfa (1, n, x);
    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 () {
    //freopen ("more.in", "r", stdin);
    while (scanf ("%d%d%d", &n, &m, &T) == 3) {
        memset (head, -1, sizeof head);
        cnt = 0;
        for (int i = 0; i < m; i++) {
            int u, v, a, b; scanf ("%d%d%d%d", &u, &v, &a, &b);
            add_edge (u, v, a, b);
        }
        printf ("%.8f\n", asr (0, T, eps)/T);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章