【01分数规划】ABC324F

[ABC324F] Beautiful Path - 洛谷

【01分数规划】ABC324F_第1张图片

思路

首先看到这个形式很容易想到 01 分数规划,即去二分答案,然后就是转化成 是否存在一个路径使得 sigma b - mid * sigma c >= 0

显然只需要改变一下边权,跑一遍最长路即可

#include 
using namespace std;
#define ll long long
#define double long double
const int N = 200200;
const double eps = 1e-15;
int n, m;
int deg[N];
struct Edge {
    int nxt;
    int to;
    int w1;
    int w2;
    Edge() {}
    Edge(int x, int y, int w, int z)
        : nxt(x), to(y), w1(w), w2(z) {}
} e[N << 2];
int h[N], cnt;
void add(int u, int v, int w1, int w2) {
    e[++cnt] = Edge(h[u], v, w1, w2);
    h[u] = cnt;
    return;
}
double L = 0, R = 2e17;
double mx[N];
bool check(double x) {
    for (int i = 1; i <= n; ++i) {
        mx[i] = -2e17;
    }
    mx[1] = 0;
    for (int u = 1; u <= n; ++u) {
        for (int i = h[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            double w1 = e[i].w1, w2 = e[i].w2;
            mx[v] = max(mx[v], mx[u] + w1 - x * w2);
        }
    }
    if (mx[n] >= 0)
        return 1;
    return 0;
}
signed main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; ++i) {
        int u, v, w1, w2;
        scanf("%d%d%d%d", &u, &v, &w1, &w2);
        add(u, v, w1, w2);
        deg[v]++;
    }
    while (R - L > eps) {
        double mid = (L + R) / 2.0;
        if (check(mid)) {
            L = mid;
        } else {
            R = mid;
        }
    }
    printf("%.18Lf\n", L);
    return 0;
}

 

你可能感兴趣的:(二分,动态规划,图论,算法)