[ABC324F] Beautiful Path - 洛谷
思路
首先看到这个形式很容易想到 01 分数规划,即去二分答案,然后就是转化成 是否存在一个路径使得 sigma b - mid * sigma c >= 0
显然只需要改变一下边权,跑一遍最长路即可
#include <bits/stdc++.h>
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;
}